<?php

/*
 * This file is part of the wiklite package.
 * (c) 2008 Guillermo Rauch <rauchg@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

require_once(dirname(__FILE__) . "/inc/wl.class.php");
require_once(dirname(__FILE__) . "/inc/wlToolkit.class.php");
require_once(dirname(__FILE__) . "/inc/wlRequest.class.php");
require_once(dirname(__FILE__) . "/inc/microlib.php");

define('MICROWIKI_VERSION', '3.0');

if (PHP_OS == "WIN32" || PHP_OS == "WINNT") {
	define('SPECIAL_SEPARATOR', '!');
} else {
	define('SPECIAL_SEPARATOR', ':');
}

$wikistarttime = microtime(true);

// Extend microconfig to provide config variables
class microwikiconfig extends microconfig
{
	/* BEGIN CONFIG VARS */
	var $wikiname = "MicroWiki"; // Wiki Name
	var $db_server = "localhost"; // MySQL Server (not required for WordPress)
	var $db_user = "root"; // MySQL User (not required for WordPress)
	var $db_password = ""; // MySQL Password (not required for WordPress)
	var $db_name = ""; // MySQL Database (not required for WordPress)
	var $db_tableprefix = "mw_"; // Table Prefix
	var $mw_rootpage = "Home Page"; // Wiki Root Page
	var $regusersonly = "none"; // User Registration:none,internal,WordPress
	var $regcreateuser = "yes"; // Only registered users can create new users:yes,no  
	var $wordpress_dir = ""; // Directory of WordPress (only required for WordPress) 
	var $user_cap_edit = "level_0"; // The WordPress capability required for editing.
	var $minoredittime = "6"; // Auto minor edit within minutes
	var $keeplast = "2"; // Retain history for # major edits
	var $wikistyle = "WikiStyle"; // Wiki page that contains the stylesheet
	var $loginpage = "Template:default/Login"; // Wiki page that contains the login form
	var $pathhistory = "10"; // Keep this many pages in path history
	var $linkstruct = "Crufty"; // URL output style:Friendly,Crufty
	var $can_include = "no"; // Enable PHP includes for {{include}} directive:yes,no 
	var $unklink = ""; // URI for unknown link image
	var $plugins = ""; // Array of plugin info
	var $email_format = "HTML"; // Email output style:HTML,text
	var $baselocation = ""; // URI for Wiki root page
	var $baselocation_ssl = ""; // URI for Wiki root page on SSL
	var $imageurl = ""; // URI for Wiki image directory
	var $imagedir = ""; // Directory for uploaded Wiki images
	var $lockconfig = "no"; // Lock Config:no,yes
	/* END CONFIG VARS */
	
	function precfg()
	{
		$this->switch_to_raw();
		$usingwikifile = (basename(__FILE__) == basename(remove_qs()));
		if($usingwikifile) $baseurl = dirname(remove_qs());
		else $baseurl = remove_qs();
		$baseurl = ($baseurl{strlen($baseurl)-1} == '/') ? substr($baseurl,0,-1) : $baseurl;
		
		if($this->db_name == '') {
			$this->db_name = 'wiki'; 
		}
		if($this->baselocation == '') {
			$warnok = true;
			$this->baselocation = "http://{$_SERVER['HTTP_HOST']}" . remove_qs();
			$this->baselocation = trim($this->baselocation, '/');
		}
		if($this->baselocation_ssl == '') {
			$this->baselocation_ssl = "https://{$_SERVER['HTTP_HOST']}" . remove_qs();
			$this->baselocation_ssl = trim($this->baselocation_ssl, '/');
		}
		if($this->imageurl == '') {
			$this->imageurl = "http://{$_SERVER['HTTP_HOST']}{$baseurl}/images"; 
		}
		if($this->unklink == '') {
			$this->unklink = "http://{$_SERVER['HTTP_HOST']}{$baseurl}/images/wiki_unknown.gif"; 
		}
		if($this->imagedir == '') {
			$this->imagedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'images';
		}
		if($this->wordpress_dir == '') {
			if(file_exists(dirname(__FILE__) . '/wp-config.php'))	$this->wordpress_dir = dirname(__FILE__);
			if(file_exists(dirname(dirname(__FILE__)) . '/wp-config.php'))	$this->wordpress_dir = dirname(dirname(__FILE__));
			if(file_exists(dirname(dirname(__FILE__)) . '/wp/wp-config.php'))	$this->wordpress_dir = dirname(dirname(__FILE__)) . '/wp';
			if(file_exists(dirname(dirname(__FILE__)) . '/wordpress/wp-config.php'))	$this->wordpress_dir = dirname(dirname(__FILE__)) . '/wordpress';
		}
	}
	
	function editform($echo = false)
	{
		$ureg[$this->regusersonly] = ' checked="checked" ';
		$urlo[$this->linkstruct] = ' checked="checked" ';
		$cani[$this->can_include] = ' checked="checked" ';
		$emai[$this->email_format] = ' checked="checked" ';
		$regc[$this->regcreateuser] = ' checked="checked" ';
		switch($this->regusersonly) {
		case 'internal':
			$tvis['internal'] = '';
			$tvis['WordPress'] = 'display:none;';
			break;
		case 'WordPress':
			$tvis['internal'] = 'display:none;';
			$tvis['WordPress'] = '';
			break;
		default:
			$tvis['internal'] = '';
			$tvis['WordPress'] = 'display:none;';
			break;
		}
		$this->precfg();
?>
<style type="text/css">
table input {
	border:1px solid #999999;background-color:white;font-weight:bold;
}
table td, table th {
	border-bottom: 1px solid #cccccc;
	padding: 5px 0px;
}
table th {
	padding: 5px 5px 0px;
	text-align:right;
}
</style>
<?php
if($warnok) {
	?><p>MicroWiki tries to guess these values for you, but you should verify all of them!</p><?php
}
?>
<form method="post">
<table style="width:100%;" cellspacing="0px">
	<tr>
		<th style="width:33%;">Name this wiki:</th>
		<td><input name="wikiname" value="<?php echo $this->wikiname; ?>" type="text" style="font-size:2em;width:100%;" /></td>
	</tr>
	<tr>
		<th>Table Prefix:</th>
		<td><input name="db_tableprefix" value="<?php echo $this->db_tableprefix; ?>" type="text" style="width:100%;" />
		<br /><small>The names of the tables in your database used for the wiki will start with this prefix.  "mw_" is usually a good choice.</small></td>
	</tr>
	<tr>
		<th>Wiki Root Page Name:</th>
		<td><input name="mw_rootpage" value="<?php echo $this->mw_rootpage; ?>" type="text" style="width:100%;" />
		<br /><small>This is the name of the page that will be shown when no page name is specified in the url.</small></td>
	</tr>
	<tr>
		<th>Wiki Root Page URI:</th>
		<td><input name="baselocation" value="<?php echo $this->baselocation; ?>" type="text" style="width:100%;" />
		<br /><small>This is the full URI of the root wiki page (no ending slash): http://example.com/wiki</small></td>
	</tr>
	<tr>
		<th>Wiki Root Page URI on SSL:</th>
		<td><input name="baselocation_ssl" value="<?php echo $this->baselocation_ssl; ?>" type="text" style="width:100%;" />
		<br /><small>This is the full URI of the root wiki page when accessed from via secure SSL connection (no ending slash): https://example.com/~myaccount/wiki</small></td>
	</tr>
	<tr>
		<th>Wiki Login Page Name:</th>
		<td><input name="loginpage" value="<?php echo $this->loginpage; ?>" type="text" style="width:100%;" />
		<br /><small>This optional page contains a special form that will allow editors to log in.</small></td>
	</tr>
	<tr>
		<th id="urloutputstyle">URL Output Style:</th>
		<td> 
			<label><input name="linkstruct" value="Friendly" <?php echo $urlo['Friendly']; ?> type="radio" />Friendly<br /><small>http://example.com/wiki/Home+Page/ <a href="#urloutputstyle" onclick="var v=document.getElementById('rewriterules');v.style.display=(v.style.display==''?'none':'');return false;">[show sample .htaccess]</a></small></label><br />
			<pre style="display:none;border:1px solid #cccccc;padding:5px;margin:5px;" id="rewriterules">
# ==== mod_rewrite rules for MicroWiki ====
# Add these rules to the .htaccess file in the wiki 
# directory to enable friendly-looking permalinks:

&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On

RewriteRule ^$ wiki.php [QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ wiki.php/$1 [L]

# ===== Secure Stuff =====
# Enable these if your SSL comes from another domain.

#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{HTTPS} ^on
#RewriteRule ^(.+)$ /~YOUR_SECURE_SUBDIR/wiki.php/$1 [L]
 
&lt;/IfModule&gt;
			</pre>
			<label><input name="linkstruct" value="Crufty" <?php echo $urlo['Crufty']; ?> type="radio" />Crufty<br /><small>http://example.com/wiki/wiki.php?page=Home+Page</small></label>
		</td>
	</tr>
	<tr>
		<th>Enable {{Include:<i>filename</i>}} Directive:</th>
		<td> 
			<label><input name="can_include" value="yes" <?php echo $cani['yes']; ?> type="radio" />Yes</label><br /><small>Allows PHP files to be included into wiki pages.</small><br />
			<label><input name="can_include" value="no" <?php echo $cani['no']; ?> type="radio" />No</label><br /><small>Prevents all file inclusion.</small>
		</td>
	</tr>
	<tr>
		<th>Automatic Minor Edit:</th>
		<td>Within <input name="minoredittime" value="<?php echo $this->minoredittime; ?>" type="text" size="4" /> minutes of previous edit.</td>
	</tr>
	<tr>
		<th>Retain History:</th>
		<td>Through <input name="keeplast" value="<?php echo $this->keeplast; ?>" type="text" size="4" /> major revisions.</td>
	</tr>
	<tr>
		<th>Email Output Style:</th>
		<td>
			<label><input name="email_format" value="HTML" <?php echo $emai['HTML']; ?> type="radio" />HTML<br /><small>Form responses are formatted in tables.</small></label><br />
			<label><input name="email_format" value="text" <?php echo $emai['text']; ?> type="radio" />Text<br /><small>Form responses are formatted with tabs.</small></label>
		</td>
	</tr>
	<tr>
		<th>Directory for uploaded Wiki images:</th>
		<td><input name="imagedir" value="<?php echo $this->imagedir; ?>" type="text" style="width:100%;"/>
		<br /><small>The full directory in which uploaded images should be stored.</small></td>
	</tr>
	<tr>
		<th>URI for Wiki image directory:</th>
		<td><input name="imageurl" value="<?php echo $this->imageurl; ?>" type="text" style="width:100%;" />
		<br /><small>The full URI to the directory specified above.</small></td>
	</tr>
	<tr>
		<th>Unknown Link Image URI:</th>
		<td><input name="unklink" value="<?php echo $this->unklink; ?>" type="text" style="width:100%;" />
		<br /><small>The full URI to an image that means "The page to which this link points does not exist."</small></td>
	</tr>
	<tr>
		<th>Plugins:</th>
		<td><small>Check the boxes next to any plugins that should be enabled globally.</small>
		<?php
			$plugindir = dirname(__FILE__) . "/plugins/";
			$d = dir($plugindir);
			while (false !== ($entry = $d->read())) {
				$plugin = $entry;
				if((is_dir($plugindir . $entry) && file_exists("{$plugindir}{$entry}/{$entry}.php")) || (preg_match('/\.php$/i', $entry))) {
					$checked = in_array($plugin, (array)$this->plugins) ? 'checked="checked"' : '';
					echo '<br /><label><input type="checkbox" name="plugins[]" value="' . basename($plugin) . '" ' . $checked . '/>' . basename($plugin) . '</label>';
				}
			}
		?>
		</td>
	</tr>
	<tr>
		<th style="background-color:#eeffee;">User Registration:</th>
		<td style="background-color:#eeffee;"> 
			<label><input name="regusersonly" value="none" <?php echo $ureg['none']; ?> type="radio" onclick="document.getElementById('setupforinternal').style.display='';document.getElementById('setupforwp').style.display='none';"/>None</label><br /><small>Anyone can edit any page.</small><br />
			<label><input name="regusersonly" value="internal" <?php echo $ureg['internal']; ?> type="radio" onclick="document.getElementById('setupforinternal').style.display='';document.getElementById('setupforwp').style.display='none';" />Internal</label><br /><small>Users must log in to MicroWiki's integrated user system to edit pages.</small><br />
			<label><input name="regusersonly" value="WordPress" <?php echo $ureg['WordPress']; ?> type="radio" onclick="document.getElementById('setupforinternal').style.display='none';document.getElementById('setupforwp').style.display='';" />WordPress</label><br /><small>Users must log in to WordPress to edit pages.</small>
		</td>
	</tr>
</table>
<table cellspacing="0px" id="setupforinternal" style="width:100%;<?php echo $tvis['internal']; ?>background-color:#eeffee;">
	<tr>
		<th style="width:33%;">MySQL Server Host:</th>
		<td><input name="db_server" value="<?php echo $this->db_server; ?>" type="text" style="width:100%;" />
		<br /><small>The MySQL server that hosts the database, usually "localhost".</small></td>
	</tr>
	<tr>
		<th>MySQL Database:</th>
		<td><input name="db_name" value="<?php echo $this->db_name; ?>" type="text" style="width:100%;" />
		<br /><small>The name of the MySQL database on the server.</small></td>
	</tr>
	<tr>
		<th>MySQL User:</th>
		<td><input name="db_user" value="<?php echo $this->db_user; ?>" type="text" style="width:100%;" />
		<br /><small>A user name that has access to the specified MySQL database.</small></td>
	</tr>
	<tr>
		<th>MySQL Password:</th>
		<td><input name="<?php echo ($this->db_password == '')?'db_password':'reset_db_password'; ?>" value="<?php echo ($this->db_password == '')?'':'********'; ?>" type="text" style="width:100%;" onchange="this.name='db_password';"/>
		<br /><small>The password for the specified user.  <?php if($this->db_password != '') echo '<strong>The password is already set.<strong>'; ?></small></td>
	</tr>
	<tr>
		<th>New User Creation:</th>
		<td>
			<label><input name="regcreateuser" value="no" <?php echo $regc['no']; ?> type="radio" />Anyone<br /><small>Anyone can create a new user using the special:newuser page.</small></label><br />
			<label><input name="regcreateuser" value="yes" <?php echo $regc['yes']; ?> type="radio" />Current Users<br /><small>Only current users can create new users.</small></label>
		</td>
	</tr>
</table>
<table cellspacing="0px" id="setupforwp" style="width:100%;<?php echo $tvis['WordPress']; ?>background-color:#eeffee;">
	<tr>
		<th style="width:33%;">WordPress Location:</th>
		<td><input name="wordpress_dir" value="<?php echo $this->wordpress_dir; ?>" type="text" style="width:100%;" />
		<br /><small>The full directory in which WordPress is installed, specifically the directory that contains "wp-config.php".</small></td>
	</tr>
	<tr>
		<th>Wiki-Editing Capability Name:</th>
		<td><input name="user_cap_edit" value="<?php echo $this->user_cap_edit; ?>" type="text" style="width:100%;">
		<br /><small>The capability that a WordPress user must have in order to edit the wiki.</small></td>
	</tr>
</table>
<table style="width:100%;background-color:#ffeeee;" cellspacing="0px">
	<tr>
		<th style="width:33%;">Configuration Lock:</th>
		<td><label style="font-size:1.5em;font-weight:bold;"><input name="lockconfig" <?php echo $lock['yes']; ?> value="yes" type="checkbox" />Enable Lock</label>
		<br /><small>Turning on this lock prevents this config from ever appearing or being editable from within the wiki!  To unlock the config page, you must either delete the config file or edit the config file in its native format.
		<br /><em>Do not enable the lock until you have finalized your config settings!</em></small></td>
	</tr>
</table>
<p>
	<input type="submit" name="Submit" value="Commit Changes" />
	<input type="hidden" name="config" value="editform" />
	<input type="hidden" name="unlock" value="<?php echo $_POST['unlock']; ?>" />
</p>
</form>
<?
		//parent::editform(true);
	}
}

// Extend microdb to define database table structure
class microwikidb extends microdb
{
	function microwikidb($config)
	{
		$this->t_pages = "{$config->db_tableprefix}pages";
		$this->t_users = "{$config->db_tableprefix}users";
		$this->t_formdata = "{$config->db_tableprefix}formdata";
		
		return parent::microdb($config);
	}

	function upgrade($silent = false)
	{
		global $mwconfig;
		$queries = "CREATE TABLE {$this->t_pages} (
			id int(11) NOT NULL auto_increment,
			pagename varchar(255) NOT NULL default '',
			changenote varchar(255) NOT NULL default '',
			body text NOT NULL,
			postdate datetime NOT NULL,
			author int(11) NOT NULL default 0,
			parent varchar(255) NOT NULL default '',
			minoredit int(11) NOT NULL default 0,
			password varchar(255) NOT NULL default '',
			secure int(11) NOT NULL default 0,
			linksto text NOT NULL,
			PRIMARY KEY  (id),
			KEY pagename (pagename),
			KEY author (author)
		);
		CREATE TABLE {$this->t_users} (
			userid int(11) NOT NULL auto_increment,
			username varchar(255) NOT NULL default '',
			password varchar(255) NOT NULL default '',
			permissions int(11) NOT NULL default 0,
			PRIMARY KEY  (userid),
			KEY username (username)
		);
		CREATE TABLE {$this->t_formdata} (
			data_id int(11) NOT NULL auto_increment,
			v_session int(11) NOT NULL default 0,
			v_table varchar(255) NOT NULL default '',
			v_field varchar(255) NOT NULL default '',
			v_value text default '',
			PRIMARY KEY  (data_id),
			KEY v_session (v_session),
			KEY v_table (v_table)
		);";

		return parent::upgrade($queries, true, $silent);
	}
}

// Extend microsession to enable non-WordPress authentication
class microwikisession extends microsession
{
	function do_auth($user, $pass)
	{
		global $mwconfig, $db, $current_user;

		switch($mwconfig->regusersonly) {
		case 'WordPress':
			return parent::do_auth($user, $pass, $mwconfig->user_cap_edit);
		case 'internal':
			list($euser, $epass) = $db->escape($user, $pass);
			$qry = "SELECT * FROM {$db->t_users} WHERE username='{$euser}' AND password='" . sha1($epass). "';";
			if($db->get_row($qry)) return true;
			return false;
		case 'none':
			return true;
		}
	}
	
	function activate_session()
	{
		global $db, $mwconfig;
		switch($mwconfig->regusersonly) {
		case 'WordPress':
			$userdata = get_userdatabylogin($this->session_username);
			$userobj = new WP_User($userdata->ID);
			$this->user_id = $userobj->ID;
			$this->username = $userobj->nicename;
			$this->userobj = $userobj;
			break;
		case 'internal':
			$userrow = $db->get_row("SELECT * FROM {$db->t_users} WHERE username='{$this->session_username}' AND password='". sha1($this->session_password) . "';");
			$this->user_id = $userrow->userid;
			$this->username = $userrow->username;
			$this->permissions = $userrow->permissions;
			break;
		case 'none':
			$this->user_id = 0;
			$this->username = 'anonymous';
			$this->permissions = 0;
			break;		
		}
	}
}

// Extend microrewrite to activate non-crufty URLs
class microwikirewrite extends microrewrite
{
	function init_rules()
	{
		global $mwconfig, $tableexists;
		
		$this->rules['actions'] = array('#^/special' . SPECIAL_SEPARATOR . '(install|config|upgrade|backup|restore|badlinks|rebuildall|orphans|password|new|all|recentrss|logout|newuser|ajax)$#i', 'action');
		$this->rules['images'] = array('/^\/(Image)' . SPECIAL_SEPARATOR . '(.+?)\/?(thumb|[0-9]+x[0-9]+)?$/i', 'action,image,imgattr');
		$this->rules['media'] = array('/^\/(Media)' . SPECIAL_SEPARATOR . '(.+?)\/?(edit|delete|rename)?$/i', 'action,media,imgaction');
		$this->rules['pageactions'] = array('/^\/([a-z:\'0-9_\\-\/\\s.!]+?)\/(view|edit|move|delete|image|media|upload|logout|rebuild|history|rss)(?:\/([0-9]+))?\/?$/i', 'page,action,tag');
		$this->rules['pages'] = array('/^\/([a-z:\'0-9_\\-\/\\s.!]+?)\/?$/i', 'page');
			
		
		if($mwconfig->linkstruct=='Friendly') {
			$this->links['special'] = '/special' . SPECIAL_SEPARATOR . '%special%';
			$this->links['page'] = '/%page%';
			$this->links['page_action'] = '/%page%/%action%';
			$this->links['page_action_version'] = '/%page%/%action%/%tag%';
		}
	}
	
	function outfilter($piecename, $value) {
		switch($piecename) {
		case 'page':
			return str_replace(':', SPECIAL_SEPARATOR, $value);
		}
		return $value;
	}

	function infilter($piecename, $value) {
		switch($piecename) {
		case 'page':
			return str_replace(SPECIAL_SEPARATOR, ':', $value);
		}
		return $value;
	}
}

class WikiPlugin
{
	function add_macro($macroname, $fn) 
	{
		global $extensions;
		$extensions[$macroname] = array(&$this, $fn);
	}
	function add_ajax_handler($ajaxtag, $fn) 
	{
		global $ajaxhandlers;
		$ajaxhandlers[$ajaxtag] = array(&$this, $fn);
	}
	function accumulate($accname, $acckey, $fn)
	{
		global $accumulator;
		$accumulator[$accname][$acckey][] = array(&$this, $fn);
	}
	function add_page($pagename, $fn)
	{
		global $pluginpages;
		$pluginpages[$pagename] = array(&$this, $fn);
	}
	function add_action($actionname, $fn)
	{
		global $rewrite, $actions;
		
		$newrule = array();
		$newrule['custom_' . $actionname] = array('/^\/([a-z:\'0-9_\\-\/\\s.!]+?)\/(' . $actionname . ')(?:\/([0-9a-z\s\-:!.]+))?\/?$/i', 'page,action,tag');
		
		$rewrite->rules = array_merge($newrule, $rewrite->rules);
		$actions[$actionname] = array(&$this, $fn);
	}
	function add_filter($context, $priority, $filterregex, $execute)
	{
		global $pluginfilters, $pluginfilterexec;
		$pluginfilterexec[md5($context . $filterregex)] = $execute;
		$execute = '$this->plugin_filter_callback(\'' . md5($context . $filterregex) . '\', $processmatches)';
		$pluginfilters[$context]->filters[$priority] = array($filterregex, $execute, false, 0);
	}
	function add_event($eventname, $fn)
	{
		global $events;
		$events[$eventname][] = array(&$this, $fn);
	}
	function process_params($matchers, $params)
	{
		$result = array();
		foreach($matchers as $key => $matcher) {
			foreach($params as $param) {
				if(preg_match($matcher, $param)) {
					$result[$key] = $param;
					break;
				}
			}
		}
		return $result;
	}
}

/*****  THE WIKI ENGINE *****/
class wikiengine
{
	var $context = array();
	var $filters = array();
	var $hashes = array();
	var $anchors = array();
	var $use_format = 'default';
	var $flags = array();
	var $content_type = '';
	var $edit_mode = false;
	var $use = array();
	var $base_page = '';
	var $page_name = '';
	var $prep_directives = array();
	var $skip_macros = array();
	var $headings = array();
	var $linksto = array();
	var $media = '';
	var $footnotes = array();
	var $used_variables = array();
	var $inserts = array();
	
	function wikiengine($parentwiki = false)
	{
		if($parentwiki)
		{
			$this->use = $parentwiki->use;
			$this->anchors = $parentwiki->anchors;
			$this->base_page = $parentwiki->base_page;
			$this->page_name = $parentwiki->page_name;
			$this->page_rec = $parentwiki->page_rec;
			$this->display_name = $parentwiki->display_name;
			$this->skip_macros = $parentwiki->skip_macros;
		}
		$this->setup_filters();
	}
	
	function setup_filters()
	{
		global $pluginfilters;
	
		$this->context['default']->filters[0] = array('/^\\(([a-z]+)(\\|[^>]+)?'.'>(.*?)<\\1\\)/sime', "\$this->newcontext('\\1', '\\3', '\\2')", true, 0);
		//$this->context['default']->filters[10] = array('/<nowiki>(.*?)<\/nowiki>/se', "\$processmatches[1]", true, 0);
		$this->context['default']->filters[10] = array('/<nowiki>(.*?)<\/nowiki>/sie', '$this->rollup(stripslashes(\'\\1\'))', true, 0);
		$this->context['default']->filters[11] = array('/`(.*?)`/se', "stripslashes('<blockquote>\\1</blockquote>')", true, 0);
		$this->context['default']->filters[12] = array('/^\\/\\/(.*?)$/sem', "''", true, 0);

		$this->context['default']->filters[40] = array('/\[\[#(.+?)\]\]/e', '$this->namedanchor("\\1")', true, 0);
		
		$this->context['default']->filters[48] = array('/\[\[\*(.+?)\]\]/e', '$this->footnote("\\1")', true, 0);

		$this->context['default']->filters[50] = array('/\\[\\[(\\b(?:https?|ftp|file|mail|mailto):\/\/[-A-Z0-9+&@#\\%?=~_!:,.;|]*[-A-Z0-9+&@#\\%=~_|])\\s([^\\]]+?)\\]\\]/ie', '$this->link(stripslashes("\\1"), stripslashes("\\2"))', true, 0);
		$this->context['default']->filters[51] = array('/\[\[(.+?)\]\](\w*)/e', '$this->link(stripslashes("\\1"), "", stripslashes("\\2"))', true, 0);
		$this->context['default']->filters[52] = array('/\\[(\\b(?:https?|ftp|file|mail|mailto):\/\/[-A-Z0-9+&@#\\%?=~_!:,.;]*[-A-Z0-9+&@#\\%=~_])\\s([^\\]]+?)\\]/ie', '$this->link(stripslashes("\\1"), stripslashes("\\2"))', true, 0);
		$this->context['default']->filters[55] = array('/\\[\\[([^|]+?)\\|([^\\]]+?)\\]\\]/ie', '$this->link(stripslashes("\\1"), stripslashes("\\2"))', true, 0);
		$this->context['default']->filters[60] = array('/\\[([^|]+?)\\|([^\\]]+?)\\]/ie', '$this->link(stripslashes("\\1"), stripslashes("\\2"))', true, 0);
		$this->context['default']->filters[80] = array('/\\b(https?|ftp|file|mail|mailto):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/ie', '$this->link(stripslashes("\\0"))', true, 0);

		$this->context['default']->filters[100] = array('/^(=+)([^=\\n]+?)\\1/me', '$this->heading("\\2", strlen("\\1"))', true, 0);
		$this->context['default']->filters[200] = array('/\*([^\n\s*][^\n*]*)\*/Use', "stripslashes('<strong>\$1</strong>')", false, 0);
		$this->context['default']->filters[201] = array('/\'\'\'(.*?)\'\'\'/sme', "stripslashes('<strong>\$1</strong>')", false, 0);
		$this->context['default']->filters[210] = array('/\b__([^\n]*)__\b/Use', "stripslashes('<u>\$1</u>')", false, 0);
		$this->context['default']->filters[220] = array('/\b_([^\n]*)_\b/Use', "stripslashes('<em>\$1</em>')", false, 0);
		$this->context['default']->filters[221] = array('/(?<!\')\'\'(?!\')(.*?)\'\'/Use', "stripslashes('<em>\$1</em>')", false, 0);
		$this->context['default']->filters[222] = array('/\^\^([^\n]*)\^\^/Use', "stripslashes('<sup>\$1</sup>')", false, 0);
		
		$this->context['default']->filters[300] = array('/(^([*#;>][^\\n\\r]+([\\n\\r]+|$))+)/me', "\$this->textblock('\$0')", false, 0);

		$this->context['default']->filters[400] = array('/^-{4}/m', "<hr/>", false, 0);
		$this->context['default']->filters[410] = array('/^====$/m', "<hr style=\"height:5px;\"/>", false, 0);
		
		$this->context['default']->filters[500] = array('/^--(([^:\/]*?)(\/([^:-]+))?)--:(.*):--\\2\\3--/sime', "\$this->div('\$5', '\$2', '\$4')", false, 0);
		$this->context['default']->filters[510] = array('/^{\\|(.*?)$(.*?)^\\|}/sme', "\$this->table('\$1', '\$2')", true, 0);
		

		$this->context['htmlform']->filters[100] = array('/^.*$/se', "\$this->formprocessing('\\0')", true, 0);		

		$this->context['vtable']->filters[100] = array('/^.*$/se', "\$this->vtable('\\0')", true, 0);	
		
		foreach((array)$pluginfilters as $context => $filters) {
			$this->context[$context]->filters = $filters->filters;
		}	
	}
	
	function load_plugins()
	{
		global $mwconfig;
		if($mwconfig->plugins != '') {
			$plugins = $mwconfig->plugins;
			$plugins = preg_replace('/\.\//', '/', $plugins);
			$plugins = preg_replace('/\/\//', '/', $plugins);
			//$plugins = array_map(create_function('$a', 'return dirname(__FILE__) . "/plugins/{$a}";'), $plugins);
			$plugins = array_map(create_function('$a', '$a = dirname(__FILE__) . "/plugins/{$a}"; return is_dir($a)? "{$a}/".basename($a).".php" : $a;'), $plugins);
			return $plugins;
		}
		else
			return array();
	}
	
	function plugins_loaded()
	{
	}
	
	function plugin_filter_callback($callback, $matches)
	{
		global $pluginfilterexec;
		return call_user_func($pluginfilterexec[$callback], $matches, $this);
	}
	
	function newcontext($context, $content, $params)
	{
		$content = stripslashes($content);
		$params = trim($params, '|');
		parse_str($params, $pary);
		$nw = new wikiengine($this);
		foreach($pary as $pkey=>$pele) {
			$nw->$pkey = $pele;
		}
		$nw->flags[] = 'nopee';
		$body = $nw->process($content, $context);
		$this->linksto = array_merge($this->linksto, $nw->linksto);
		return $this->rollup($body);
	}
	
	function vtable($content)
	{
		global $db, $mwconfig;
		
		$content = stripslashes($content);

		$rawdata = $db->get_results("SELECT * FROM {$db->t_formdata} WHERE v_table = '{$this->vtable}';");
		
		foreach($rawdata as $e) {
			$tdata[$e->v_session][$e->v_field] = $e->v_value;
		}
		unset($rawdata);
		$output = '';
		foreach($tdata as $row) {
			$output .= preg_replace('/%([a-z_0-9]+)%/ie', '$row["\\1"]', $content);
		}
		return $output;
	}
	
	function gettabledata($page, $field, $index)
	{
		$tabletext = $this->getrawpage($page, $pagerow);
		if(preg_match('/^\\{\\|(.*?)$(.*?)^\\|\\}/sim', $tabletext, $matches)) {
			$tabletext = $matches[2];
			$items = explode("\n", $tabletext);
			$fielddef = true;
			$findex = -1;
			foreach($items as $item) {
				$item = trim($item);
				if($item == '') continue;
				if($fielddef) {
					$fielddef = false;
					$fields = explode(",", $item);
					$findex = array_search($field, $fields);
					continue;
				}
				if($findex == -1) {
					return false;
				}
				$realitem = explode(',', $item);
				if($realitem[0] == $index) {
					return $realitem[$findex];
				}
			}
		}
		return false;
	}
	
	function rollup($x)
	{
		$hash = chr(2) . 'B' . md5($x). chr(2) . 'E';
		//$this->hashes[$hash] = $x;
		global $qhashes;
		$qhashes[$hash] = $x;
		return $hash;
	}
	
	function unroll($x)
	{
		global $qhashes;
		if(!is_array($qhashes)) return $x;
		$this->hashes = $qhashes;
		$key = array_keys($this->hashes);
		$value = array_values($this->hashes);
		$x = str_replace($key, $value, $x);
		foreach($key as $pattern) {
			if(strstr($x, $pattern)) {
				$x = $this->unroll($x);
				break;
			}
		}
		return $x;
	}
	
	function imagetag($file, $attribs)
	{
		global $rewrite;
	
		$style = '';
		$alt = '';
		$dothumb = false;
		$urlonly = false;
		$prefix = 'Image';
		foreach($attribs as $attr) {
			if(strtolower($attr) == 'left') {
				$style .= 'float:left;';
			}
			elseif(strtolower($attr) == 'right') {
				$style .= 'float:right;';
			}
			elseif(strtolower($attr) == 'center') {
				$style .= 'margin-left:auto;margin-right:auto;display:block;';
			}
			elseif(strtolower($attr) == 'thumb') {
				$rewrite_ary['action'] = 'thumb';
				$wrapper = '<div class="wikithumb">$img</a><br/>$alt</div>';
				$dothumb = true;
			}
			elseif(strtolower($attr) == 'noprefix') {
				$prefix = '';
			}
			elseif(strtolower($attr) == 'media') {
				$prefix = 'Media';
			}
			elseif(strtolower($attr) == 'none') {
				$style .= 'float:none;';
			}
			elseif(strtolower($attr) == 'urlonly') {
				$urlonly = true;
			}
			elseif(preg_match('/^[0-9]+x[0-9]+$/i', $attr)) {
				$rewrite_ary['action'] = $attr;
			}
			else {
				$alt = $attr;
			}
		}
		$rewrite_ary['page'] = "{$prefix}" . SPECIAL_SEPARATOR . "{$file}";
		$style = ($style == '') ? '' : " style=\"{$style}\"";
		$aalt = ($alt == '') ? " alt=\"{$file}\"" : " alt=\"{$alt}\"";
		if($urlonly) {
			return $rewrite->get_link($rewrite_ary);
		}
		if($dothumb) {
			$imgout = '<div $style class="wikithumb"><a href="' . $rewrite->get_link(array('page'=>"Media" . SPECIAL_SEPARATOR . "{$file}")) . '"><img src="' . $rewrite->get_link($rewrite_ary) . '"$aalt/></a><br/>$alt</div>';
		}
		else {
			$imgout = '<img src="' . $rewrite->get_link($rewrite_ary) . '"$aalt$style/>';
		}
		$imgout = str_replace('$alt', $alt, $imgout);
		$imgout = str_replace('$aalt', $aalt, $imgout);
		$imgout = str_replace('$style', $style, $imgout);
		return $imgout;
	}
	
	function texttobookmark($text)
	{
		$bookmark = $this->unroll($text);
		$bookmark = preg_replace('/[\s]+/', '-', strip_tags($bookmark));
		$bookmark = preg_replace('/[^a-z0-9\-]+/i', '', strip_tags($bookmark));
		return $bookmark;
	}
	
	function heading($text, $depth)
	{
		$text = stripslashes($text);
		$this->headings[] = array($text, $depth);
		$bookmark = $this->texttobookmark($text);
		return "<h{$depth} id=\"{$bookmark}\">{$text}</h{$depth}>\n";
	}
	
	function footnote($text)
	{
		$footindex = 0;
		foreach($this->footnotes as $footnote) {
			$footindex++;
			if($footnote == $text) {
				return '<sup><a href="#wikifootnotes_' . $footindex .'">' . $footindex . '</a></sup>';
			}
		}
		$this->footnotes[] = $text;
		return '<sup><a href="#wikifootnotes_' . count($this->footnotes) .'">' . count($this->footnotes) . '</a></sup>';
	}
	
	function link($href, $text = '', $postfix = '')
	{
		global $rewrite, $db, $mwconfig, $session;

		if((strpos($href, '|') > 0) && ($text == '')) {
			list($href, $text) = explode('|', $href, 2);
		}
		
		if(in_array('link', $this->skip_macros)) return ($text == '') ? $href : $text;
		
		if($href{0} == '^') {
			$popup = ' onclick="window.open(this.href, \'wikipop\', \'toolbar=0,scrollbars=1,statusbar=0,menubar=0\');return false;"';
			$href = substr($href, 1);
		}
		else {
			$popup = '';
		}
		if(substr($href, 0, 5) == '&#36;') {
			$href = substr($href, 5);
			$secure = true;
		}
		else if(substr($href, 0, 1) == '$') {
			$href = substr($href, 1);
			$secure = true;
		}
		else {
			$secure = false;
		}
		
		if(preg_match('/\\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/ie', $href)) {
			if('' == $text) {
				if(in_array($href, $this->anchors)) {
					$flip = array_flip($this->anchors);
					$index = $flip[$href];
				}
				else {
					$index = count($this->anchors) + 1;
					$this->anchors[$index] = $href;
				}
				$text = "[{$index}]";
			}
			return $this->rollup("<a href=\"{$href}\"{$popup} class=\"microwiki offsite\">") . $text . $postfix . "</a>";
		}
		elseif(preg_match('/\\b(mail|mailto):\/?\/?([-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ie', $href, $mailmatch)) {
			if('' == $text) {
				$text = $mailmatch[2];
			}
			return $this->rollup("<a href=\"{$href}\" class=\"microwiki email\">") . $text . $postfix . "</a>";
		}
		else {
			if($href{0} == ':') {
				list($namesp, $basename) = explode(':', $this->page_name);
				$href = $namesp . $href;
			}
			$pageref = explode('#', $href, 2);
			if(count($pageref) > 1) {
				$pageexists = $this->page_exists($pageref[0]);
				if($pageexists) {
					$nw = new wikiengine();
					$nw->skip_macros[] = 'link';
					$body = $nw->getpage($pageref[0], $pagerow);
					$pmatch = str_replace(' ', '[\+ ]', $pageref[1]);
					$pmatch = str_replace('/', '\\/', $pmatch);
					if(!preg_match('/(name|id)\s*=\s*"' . $pmatch . '"/i', $body)) {
						$pageexists = false;
					}
				}
				$pageref = $pageref[0];
			}
			else {
				$pageref = $href;
				$pageexists = $this->page_exists($pageref);
			}
			$this->linksto[] = $pageref;
			if($pageexists) {
				$href_link = $rewrite->get_link(array('page'=>$href), $secure);
				if($secure) $href_link = match_scheme($href_link, 'https');
				if($text == '') {
					$pageref2 = $pageref;
					if(strpos($pageref2, '/') !== false) $pageref2 = basename($pageref);
					if(strpos($pageref2, ':') !== false) list($namesp, $pageref2) = explode(':', $pageref2);
					return $this->rollup("<a href=\"{$href_link}\"{$popup} class=\"microwiki\">") . $pageref2 . $postfix . "</a>";
				}
				else {
					return $this->rollup("<a href=\"{$href_link}\"{$popup} class=\"microwiki\">") . $text . $postfix . "</a>";
				}
			}
			else {
				$href_link = $rewrite->get_link(array('page'=>$pageref, 'action'=>'edit'));
				
				$ulinktext = ($mwconfig->unklink == '') ? '[?]' : '<img src="' . $mwconfig->unklink . '" alt="edit" />';
				
				if($session->is_auth()) {
					if($text == '') {
						return $this->rollup("<a href=\"{$href_link}\"{$popup} class=\"microwiki wikiunknown\">" . $pageref . $postfix . "{$ulinktext}</a>");
					}
					else {
						return $this->rollup("<a href=\"{$href_link}\"{$popup} class=\"microwiki wikiunknown\">" . $text . $postfix . "{$ulinktext}</a>");
					}
				}
				else {
					if($text == '') {
						return $this->rollup("<span class=\"wikiunknown\">" . $pageref . $postfix . "</a>");
					}
					else {
						return $this->rollup("<span class=\"wikiunknown\">" . $text . $postfix . "</a>");
					}
				}
			}
		}
	}
	
	function table($attribs, $content)
	{
		$attribs = explode('/', trim($attribs));
		$id = ($attribs[0] == '') ? '' : " id=\"{$attribs[0]}\"";
		$class = ($attribs[1] == '') ? '' : " class=\"{$attribs[1]}\"";
		$cc = array_slice($attribs, 1);
		foreach($cc as $c) $colclasses[] = $c;
		
		$content = preg_replace('/\\\\"([^"]*)\\\\"/sime', "\$this->rollup(\"\\1\")", $content);
		$rows = explode("\n", $content);
		$cellstart = '<th>';
		$cellstop = '</th>';
		$output = "<table{$id}{$class}>";
		unset($rows[0]);
		$maxcolumns = 0;
		foreach($rows as $row) {
			if('' != trim($row)) {
				$maxcolumns = max(count(explode(',', $row)), $maxcolumns);
			}
		}
		$output .= '<thead>';
		for($z=0;$z<$maxcolumns;$z++) {
			$output .= '<col class="col' . ($z + 1) . '" />';
		}
		if('' != trim($rows[1])) {
			$cols = explode(',', $rows[1]);
			$output .= '<tr>';
			$colindex = 0;
			foreach($cols as $col) {
				$colindex++;
				$colclass = ($colclasses[$colindex] == '')? '' : " class=\"{$colclasses[$colindex]}\" ";
				$output .= "<th{$colclass}>" . trim($col) . '</th>';
			}
			$output .= "</tr>\n";
			unset($rows[1]);
		}
		$output .= '</thead><tbody>';
		foreach($rows as $row) {
			if('' == trim($row)) {
				continue;
			}
			$cols = explode(',', $row);
			$alt = ($alt == '')?' class="alt"':'';
			$output .= "<tr{$alt}>";
			$colindex = 0;
			foreach($cols as $col) {
				$colindex++;
				$colclass = ($colclasses[$colindex] == '')? '' : " class=\"{$colclasses[$colindex]}\" ";
				$output .= "<td{$colclass}>" . trim($col) . '</td>';
			}
			$output .= "</tr>\n";
		}
		$output .= '</tbody>';
		$output .= '</table>';
		$output = $this->unroll($output);
		return $output;
	}
	
	function div($content, $id = '', $class = '')
	{
		if($class != '') $class = " class=\"{$class}\"";
		if($id != '') $id = " id=\"{$id}\"";
		return "<div{$id}{$class}>{$content}</div>";
	}
	
	function namedanchor($href)
	{
		return $this->rollup("<a name=\"{$href}\"></a>");
	}
	
	function textblock($block)
	{
		$block = str_replace('\\"', '"', $block);
		$block = rtrim($block) . "\n";
		$type = $block{0};
		switch($type) {
		case '*':
		case '#':
			$before ='<li>';$after='</li>';
			break;
		case '>':
			$before ='';$after='<br/>';
			break;
		}
		switch($type) {
		case '*':
		case '#':
		case '>':
			$regex = '|^[*#>]([^\n]+)(?:[\n]+)|me';
			$block = preg_replace($regex, "trim('\$1').'\n'", $block);
			$block = str_replace('\\"', '"', $block);
			$block = trim(preg_replace('|^(([*#;>][^\n]+\n)+)|me', "\$this->textblock('\$0', false)", $block));
			$block = str_replace('\\"', '"', $block);
			$block = preg_replace('/^(?!<ul>|<ol>|<blockquote>)[^\\n]*/me', "'".$before."\$0".$after."'", $block);
			$block = str_replace('\\"', '"', $block);
			break;
		case ';':
			$regex = '|^;([^:\n]+):?([^\n]+)?|me';
			$block = preg_replace($regex, "'<dt>'.trim('\$1').'</dt>\n<dd>'.trim('\$2').'</dd>\n'", $block);
			$block = str_replace('\\"', '"', $block);
			break;
		}
		switch($type) {
		case '*':
			$block = "<ul>{$block}</ul>";
			break;
		case '#':
			$block = "<ol>{$block}</ol>";
			break;
		case ';':
			$block = "<dl>{$block}</dl>";
			break;
		case '>':
			$block = "<blockquote>{$block}</blockquote>";
			break;
		}
		return preg_replace('|\n|', '', $block)."\n";
	}
	
	function scriptstrip($smatch)
	{
		return $this->rollup($smatch[0]);
	}
	
	function peestrip($smatch)
	{
		return $this->rollup($smatch[1]);
	}
	
	function autop($pee, $br = 1) {
		if(trim($pee) == '') return ' ';
		$pee = preg_replace_callback('/<script.*?<\/script>/s', array(&$this, 'scriptstrip'), $pee);
		$pee = preg_replace_callback('/<nopee>(.*?)<\/nopee>/s', array(&$this, 'peestrip'), $pee);
    $pee = $pee . "\n"; // just to make things a little easier, pad the end
    $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee);
    $pee = preg_replace('!(<(?:table|ul|ol|li|pre|form|blockquote|h[1-6])[^>]*>)!', "\n$1", $pee); // Space things out a little
    $pee = preg_replace('!(</(?:table|ul|ol|li|pre|form|blockquote|h[1-6])>)!', "$1\n", $pee); // Space things out a little
    $pee = preg_replace("/(\r\n|\r)/", "\n", $pee); // cross-platform newlines
    $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates
    $pee = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "\t<p>$1</p>\n", $pee); // make paragraphs, including one at the end
    $pee = preg_replace('|<p>\s*?</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace
    $pee = preg_replace('|<p>\s*(\x02B[0-9a-f]+\x02E)\s*</p>|i', '\1', $pee); // Do not make paragraphs of only rolled up stuff 
    $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists
    $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
    $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
    $pee = preg_replace('!<p>\s*(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)!', "$1", $pee);
    $pee = preg_replace('!(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*</p>!', "$1", $pee);
    if ($br) $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // optionally make line breaks
    $pee = preg_replace('!(</?(?:table|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*<br />!', "$1", $pee);
    $pee = preg_replace('!<br />(\s*</?(?:p|li|div|th|pre|td|ul|ol)>)!', '$1', $pee);
    $pee = preg_replace('/&([^#])(?![a-z]{1,8};)/', '&#038;$1', $pee);
    
    return $pee;
	}
	
	function fileinclude($fn, $i = -1)
	{
		if($i === -1) {
			return $this->rollup($this->process(implode("\n", file(dirname(__FILE__).'/'.basename($fn)))));
		}
		else {
			$params = explode(',', $fn);
			$fl = implode('', file(dirname(__FILE__).'/'.basename($fn)));
			$regex = '/##'.preg_quote($i, '/').'##(.*?)(?=\\n[^\\n]*##(?:[^\\n]*)##|$)/si';
			if(preg_match($regex, $fl, $matches)) {
				$fl = $matches[1];
			}
			else {
				$fl = '';
			}
			$fl = str_replace('{{#}}', '#', $fl);
			return $fl;
		}
	}
	
	function a2wlul($ary, $filter = '', $cb = false, $tt='ul', $multi_cb = false)
	{
		$output = '';
		$runlevel = -1;
		$startrl = -1;
		foreach($ary as $el) {
			if(is_array($el) && !$multi_cb) {
				$els = $el[0];
				if($runlevel == -1) {
					$startrl = $runlevel;
				}
				elseif($runlevel > $el[1]) {
					$output .= "</{$tt}></li>\n";
				}
				elseif($runlevel < $el[1]) {
					$output = substr($output, 0, strlen($output) - 6);
					$output .= "<{$tt}>\n";
				}
				$runlevel = $el[1];
			}
			else {
				$els = $el;
			}
			if($filter != '') {
				if(!preg_match($filter, $els)) continue;
			}
			if($cb) {
				if($multi_cb) {
					$output .= "<li>" . call_user_func_array($cb, $els) . "</li>\n";
				}
				else {
					$output .= "<li>" . call_user_func($cb, $els) . "</li>\n";
				}
			}
			else {
				$output .= "<li>" . $this->link($els) . "</li>\n";
			}
		}
		while($runlevel > $startrl) {
			$runlevel --;
			$output .= "</{$tt}>\n";
		}
		return "<{$tt}>\n{$output}</{$tt}>\n";
	}
	
	function headinglink($heading)
	{
		$bookmark = $this->texttobookmark($heading);
		return $this->link("{$this->page_name}#{$bookmark}", $heading);
	}
	
	function revision_link($a, $b)
	{
		global $rewrite;
		$viewlink = $rewrite->get_link(array("page"=>$this->page_name, "action"=>"view", "tag"=>$a));
		$editlink = $rewrite->get_link(array("page"=>$this->page_name, "action"=>"edit", "tag"=>$a));
		$revdate = date("Y-m-d H:i", strtotime($b));
		$output = "
			<a href=\"{$viewlink}\">{$revdate}</a> 
			<a href=\"{$editlink}\" onclick=\"return confirm(\'Are you sure you want to edit this old version and use it as the current page?\');\"
			>&Delta;</a>
		";
		return $output;
	}

	function authorname($id)
	{
		global $mwconfig, $db;
		if($id==0) return 'anonymous';
		switch($mwconfig->regusersonly) {
		case 'WordPress':
			$userobj = new WP_User($id);
			return $userobj->nickname;
		case 'internal':
			$edituser = $db->get_row("SELECT * FROM {$db->t_users} WHERE userid = {$id}");
			return $edituser->username;
		case 'none':
			return 'anonymous';
		}
	}
	
	function macro($ref, $paramstr)
	{
		global $mwconfig, $rewrite, $db, $session, $extensions, $accumulator, $body;

		$params = explode('|', $paramstr);
		$refs = explode(':', $ref, 2);
		if(in_array(strtolower($refs[0]), $this->skip_macros)) return '';
		if(in_array(strtolower($ref), $this->skip_macros)) return '';
		if(isset($extensions[$refs[0]])) {
			$params[0] = $refs[1];
			$out = call_user_func_array($extensions[$refs[0]], $params);
			return $this->rollup($out);
		}
		switch(strtolower($refs[0])) {
		case 'file':
			return $this->fileinclude($refs[1], $params[1]);
		case 'include':
			if($mwconfig->can_include == 'yes') {
				ob_start();
				include $refs[1];
				return $this->rollup(ob_get_clean());
			}
			else
				return "Configuration does not permit including {$refs[1]}.";
		case 'includeonce':
			if($mwconfig->can_include == 'yes') {
				ob_start();
				include_once $refs[1];
				return $this->rollup(ob_get_clean());
			}
			else
				return "Configuration does not permit including {$refs[1]}.";
		case 'timenow':
			return $this->rollup(date('H:i:s'));
		case 'datenow':
			return $this->rollup(date('Y-m-d'));
		case 'datetime':
			return $this->rollup(date('Y-m-d H:i:s'));
		case 'format':
			$this->use_format = $refs[1];
			$this->prep_directives['format'] = $this->use_format;
			return '';
		case 'editformat':
			if($this->edit_mode) {
				$this->user_format = $refs[1];
			}
			return '';
		case 'flag':
		case 'on':
			if(!in_array($refs[1], $this->flags))
			{
				$this->flags[] = $refs[1];
			}
			return '';
		case 'noformat':
			$this->use_format = '';
			return '';
		case 'content-type':
			$this->content_type = $refs[1];
			return '';
		case 'set':
			$this->use[$refs[1]] = $params[1];
			$this->prep_directives[] = $params[1];
			return '';
		case 'use':
			$this->used_variables[] = $refs[1];
			if($this->use[$refs[1]] != '') {
				$ref = $this->use[$refs[1]];
			}
			else {
				$ref = $params[1];
			}
			break;
		case 'forcesecure':
			if(!($rewrite->is_secure() || $_POST['save'])) {
				header("location: ". $rewrite->get_link(array('page'=>$this->page_name), true));
				exit;
			}
			return '';
		case 'loginonly':
			if(!$session->is_auth()) {
				$this->flags[] = 'loginonly';
			}
			return '';
		case 'image':
			$this->linksto[] = "Media" . SPECIAL_SEPARATOR . "{$refs[1]}";
			return $this->rollup($this->imagetag($refs[1], $params));
		case 'gallery':
			return $this->rollup($this->gallery($refs[1], $params));
		case 'pageurl':
			$pageurl = $refs[1] == '' ? $this->page_name : $refs[1];
			if($params[1] != '') {
				return $this->rollup($rewrite->get_link(array('page'=>$pageurl, 'action'=>$params[1])));
			}
			else {
				return $this->rollup($rewrite->get_link(array('page'=>$pageurl)));
			}
			break;
		case 'input':
			switch($refs[1]) {
			case 'select':
				$output = "<select name=\"{$params[1]}\">";
				$optiontext = $this->getrawpage($params[2], $pagerow);
				$this->prep_directives[] = $params[2];
				$items = explode("\n", $optiontext);
				$skipnext = false;
				foreach($items as $item) {
					if(preg_match('#^(\{\||\|\})#', $item)) {
						$skipnext = true;
						continue;
					}
					if($skipnext) {
						$skipnext = false;
						continue;
					}
					$realitem = explode(',', $item, 2);
					$output .= "<option>{$realitem[0]}</option>";
				}
				$output .= "</select>";
				return $output;
			}
			break;
		case 'config':
			return $refs[1] == 'db_password' ? '' : $mwconfig->$refs[1];
		case 'nsurl':
			if(strpos($this->page_name, ':') !== false) {
				list($namesp, $basename) = explode(':', $this->page_name);
				$pname = (($refs[1]=='default') ? '' : ($refs[1] . ':')) . $basename;
			} else {
				$pname = (($refs[1]=='default') ? '' : ($refs[1] . ':')) . $this->page_name;
			}
			if(isset($params[1])) {
				return $rewrite->get_link(array('page'=>$pname, 'action'=>$params[1]));
			}
			else {
				return $rewrite->get_link(array('page'=>$pname));
			}
		case 'actionurl':
			$props = array();
			if($refs[1] != 'view') $props['action'] = $refs[1];
			if(isset($params[1])) {
				if(strpos($this->page_name, ':') !== false) {
					list($namesp, $basename) = explode(':', $this->page_name);
					$pname = (($params[1]=='default') ? '' : ($params[1] . ':')) . $basename;
				} 
				else {
					$pname = (($params[1]=='default') ? '' : ($params[1] . ':')) . $this->page_name;
				}
				$props['page'] = $pname;
			}
			else {
				$props['page'] = $this->page_name;
			}
			return $rewrite->get_link($props);
		case 'audioblog':
			$outtag = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" height="20" width="246"><param name="allowScriptAccess" value="sameDomain"><param name="menu" value="false"><param name="wmode" value="transparent"><param name="movie" value="http://www.audioblog.com/client/player/en_us/aplayer21.swf?v=14"><param name="FlashVars" value="audioid='.$refs[1].'&amp;buffer=5&amp;fc=FFFFFF&amp;pc=CCFF33&amp;kc=FFCC33&amp;bc=FFFFFF&amp;gateway=http%3A%2F%2Fwww.audioblog.com%2Fplaylist"><param name="quality" value="high"><param name="bgcolor" value="#"><embed src="http://www.audioblog.com/client/player/en_us/aplayer21.swf?v=14" flashvars="audioid='.$refs[1].'&amp;buffer=5&amp;fc=FFFFFF&amp;pc=CCFF33&amp;kc=FFCC33&amp;bc=FFFFFF&amp;gateway=http%3A%2F%2Fwww.audioblog.com%2Fplaylist" quality="high" wmode="transparent" bgcolor="#" allowscriptaccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="20" width="246"></object>';
			return $this->rollup($outtag);
		case 'wp':
			global $wp_query;
			if(!function_exists('get_header')) return $this->rollup('<!--WordPress not found-->');
			$wp_query->query_vars = array();
			switch($refs[1]) {
			case 'header':
				ob_start();
				get_header();
				return $this->rollup(ob_get_clean());
			case 'footer':
				ob_start();
				get_footer();
				return $this->rollup(ob_get_clean());
			case 'sidebar':
				ob_start();
				get_sidebar();
				return $this->rollup(ob_get_clean());
			case 'template':
				ob_start();
				$template = str_replace('..', '', $params[1]);
				include get_query_template($template);
				return $this->rollup(ob_get_clean());
			case 'bloginfo':
				return $this->rollup(get_bloginfo($params[1]));
			}
		case 'acc':
		case 'accumulator':
			if(isset($accumulator[$refs[1]])) {
				$out = '';
				foreach($accumulator[$refs[1]] as $fns) {
					$check = '';
					foreach($fns as $fn) {
						$check = call_user_func_array($fn, $params);
						if($check != '') break;
					}
					$out .= $check; 
				}
				return $this->rollup($out);
			}
			return '';
		case 'special':
			switch($refs[1]) {
			case 'preview':
				if(isset($_POST['pagecontent'])) { //$this->preview_mode) {
					$nw = new wikiengine();
					if (get_magic_quotes_gpc()) {
						$pagecontent = stripslashes($_POST['pagecontent']);
					}
					return '<div id="wikipreview"><div id="wikipreviewtitle">Preview:</div>' . $nw->process($nw->preprocess($pagecontent)) . '</div>';
				}
				else {
					return '';
				}
			case 'recursiveincludes':
				if(isset($this->flags['loginonly'])) return '';
				$pages = array($this->page_name);
				$i = 0;
				while($i<count($pages)) {
					$nw = new wikiengine();
					$nw->skip_macros[] = 'special:includes';
					$nw->skip_macros[] = 'special:variables';
					$nw->getpage($pages[$i], $nil, false);
					foreach($nw->prep_directives as $page) {
						if(!in_array($page, $pages)) $pages[] = $page;
					}
					$i++;
				}
				return $this->a2wlul(array_unique($nw->prep_directives), '/^(?!((file|include|flag|on|format|special|image|set|use|content-type|pageurl):)|noformat)/i');
			case 'includes':
				if(isset($this->flags['loginonly'])) return '';
				$nw = new wikiengine();
				$nw->skip_macros[] = 'special:includes';
				$nw->skip_macros[] = 'special:variables';
				$nw->getpage($this->page_name, $nil, false);
				return $this->a2wlul(array_unique($nw->prep_directives), '/^(?!((file|include|flag|on|format|special|image|set|use|content-type|pageurl):)|noformat)/i');
			case 'headings':
				if(isset($this->flags['loginonly'])) return '';
				$nw = new wikiengine();
				$nw->skip_macros[] = 'special:headings';
				$nw->getpage($this->page_name, $nil);
				return $this->a2wlul($nw->headings, '', array(&$this, 'headinglink'));
			case 'subpages':
				if(isset($this->flags['loginonly'])) return '';
				$dirname = $db->escape($this->page_name);
				$pages = $db->get_col("SELECT DISTINCT pagename FROM {$db->t_pages} WHERE pagename LIKE '{$dirname}/%';");
				$pages = array_filter((array)$pages, create_function('$a', 'return (strpos(substr($a, ' . (strlen($dirname) + 1) . '), "/") === false);'));
				return $this->a2wlul($pages, '', false, 'ul class="wikisubpages"');
			case 'allsubpages':
				if(isset($this->flags['loginonly'])) return '';
				$dirname = $db->escape($this->page_name);
				$pages = $db->get_col("SELECT DISTINCT pagename FROM {$db->t_pages} WHERE pagename LIKE '{$dirname}/%';");
				return $this->a2wlul($pages, '', false, 'ul class="wikisubpages"');
			case 'siblingpages':
				if(isset($this->flags['loginonly'])) return '';
				$dirname = $db->escape(dirname($this->page_name));
				$pages = $db->get_col("SELECT DISTINCT pagename FROM {$db->t_pages} WHERE pagename LIKE '{$dirname}/%';");
				$pages = array_filter((array)$pages, create_function('$a', 'return (strpos(substr($a, ' . (strlen($dirname) + 1) . '), "/") === false);'));
				return $this->a2wlul($pages, '', false, 'ul class="wikisiblingpages"');
			case 'pagelist':
				if(isset($this->flags['loginonly'])) return '';
				if(isset($params[1])) {
					$pages = $db->get_col("SELECT distinct(pagename) FROM {$db->t_pages} WHERE pagename LIKE '{$params[1]}:%' ORDER BY pagename");
				}
				else {
					$pages = $db->get_col("SELECT distinct(pagename) FROM {$db->t_pages} ORDER BY pagename");
				}
				return $this->a2wlul($pages);
			case 'ancestry':
				$linkpage = $this->page_name;
				$outp = '';
				while(($linkpage = dirname($linkpage)) != '.' && ($linkpage != '')) {
					$outp = "<li>" . $this->link($linkpage) . "</li>\n" . $outp;
				}
				return ($outp=='')?'':"<ul id=\"wikiancestry\">{$outp}</ul>";
			case 'parentpage':
				if(dirname($this->page_name) != '.') {
					return $this->link(dirname($this->page_name));
				}
				return '';
			case 'redirect':
				return $this->rollup('{{{location: ' . $rewrite->get_link(array('page'=>$params[1])) . '}}}');
			case 'media':
				return $this->imagetag($this->media, array());
			case 'mediapage':
				$mediapage = 'Media' . SPECIAL_SEPARATOR . $this->normalize_str($this->media);
				return $this->rollup($this->pageinclude($mediapage));
			case 'medianame':
				return $this->media;
			case 'basepage':
				$basepage = $this->unroll($this->base_page);
				if(in_array('striptags', $params)) $basepage = strip_tags($basepage);
				if(($dex = array_search('trunc', $params)) !== FALSE) $basepage = substr($basepage, 0, $params[$dex+1]);
				return $this->rollup($basepage);
			case 'baseedit':
				if(isset($_POST['pagecontent'])) { //$this->preview_mode) {
					if (get_magic_quotes_gpc()) $pagecontent = stripslashes($_POST['pagecontent']);
					return str_replace('{', '&#123;', $pagecontent);
				}
				else {
					return $this->base_page;
				}
			case 'basename':
				if($this->display_name == '') $this->display_name = basename($this->page_name);
				if(strpos($this->display_name, ':') !== false) {
					list($namesp, $basename) = explode(':', $this->display_name);
				} else {
					$basename = $this->display_name;
				}
				return $basename;
			case 'pagename':
				return ($this->media == '') ? $this->page_name : $this->media;
			case 'postdate':
				if(isset($this->page_rec->postdate)) 
					return date(($params[1]=='')?'Y-m-d H:i:s':$params[1], @strtotime($this->page_rec->postdate));
				else
					return 'Unknown';
			case 'currentdate':
				return date(($params[1]=='')?'Y-m-d H:i:s':$params[1]);
			case 'author':
				return $this->authorname($this->page_rec->author);
			case 'sitename':
			case 'wikiname':
				return ($mwconfig->wikiname);
			case 'showuse':
				$out = "\n";
				foreach($this->use as $use) $out .= "* {$use}\n";
				return $out;
			case 'wikiroot':
				$base = $rewrite->base();
				if(strstr($base, basename(__FILE__))) {
					$base = dirname($base);
				}
				return $base;
			case 'edit':
				if(isset($params[2])) {
					$editurl = $rewrite->get_link(array('page'=>$this->normalize_str($params[2]), 'action'=>'edit'));
				}
				else {
					$editurl = $rewrite->get_link(array('page'=>$this->normalize_str($this->page_name), 'action'=>'edit'));
				}
				if(isset($params[1])) {
					return $this->rollup('<a href="' . $editurl . '">' . $params[1] . '</a>');
				}
				else {
					return $editurl;
				}
			case 'phpinfo':
				ob_start();
				phpinfo(32);
				$php_info = ob_get_contents();
				ob_end_clean();
				preg_match_all('/<td class="e">(.*?)<\/td><td class="v">(.*?)<\/td>/sim', $php_info, $matches, PREG_SET_ORDER);
				$ret = '<dl class="wikiphpinfo phpinfo>';
				foreach($matches as $match) {
					$ret .= "<dt>{$match[1]}</dt>\n<dd>{$match[2]}</dd>\n";
				}
				$ret .= '</dl>';
				return $this->rollup($ret);
			case 'server':
				return $this->rollup($_SERVER[$params[1]]);
			case 'secure':
				if($this->secure_page) 
					return $this->rollup($params[1]);
				return '';
			case 'linksout':
				$epage_name = $db->escape($this->page_name);
				$qry = "SELECT linksto FROM {$db->t_pages} WHERE pagename ='{$epage_name}';";
				$linksout = explode(',', $db->get_var($qry));
				$res = '<ul>';
				foreach($linksout as $link) {
					$res .= "<li>" . $this->link($link) . "</li>\n";
				}
				$res .= '</ul>';
				return $res;
			case 'linksin':
				$pagesearch = $db->escape($this->page_name);
				$qry = "SELECT distinct pagename FROM {$db->t_pages} WHERE linksto RLIKE '{$pagesearch}';";
				if($linksin = $db->get_results($qry)) {
					$res = '<ul>';
					foreach($linksin as $link) {
						$res .= "<li>" . $this->link($link->pagename) . "</li>\n";
					}
					$res .= '</ul>';
				}
				else {
					$res = $params[1];
				}
				return $res;
			case 'inminorcheck':
				$epage_name = $db->escape($this->page_name);
				if($mins = $db->get_var("SELECT ((cast(unix_timestamp(now()) as signed integer) - cast(unix_timestamp(max(postdate)) as signed integer)) / 60) FROM {$db->t_pages} WHERE pagename = '{$epage_name}';", 'row')) {
					if($mins <= $mwconfig->minoredittime) return ' checked="checked" ';
				}
				return '';
			case 'new':
				$templates = $db->get_col("SELECT distinct(pagename) FROM {$db->t_pages} ORDER BY postdate DESC limit 10");
				return $this->a2wlul($templates, '', create_function('$a', 'return "<a href=\"#\" onclick=\"editInsert(\'{$a}\');return false;\">" . substr($a,9) . "</a>";'));
			case 'templates':
				$templates = $db->get_col("SELECT distinct(pagename) FROM {$db->t_pages} WHERE lower(substring(pagename, 1, 9)) = 'template:'");
				return $this->a2wlul($templates, '', create_function('$a', 'global $rewrite; return "<a href=\"" . $rewrite->get_link(array("page"=>$a, "action"=>"edit")) . "\" onclick=\"editInsert(\'\{\{{$a}\}\}\');return false;\">" . substr($a,9) . "</a>";'));
			case 'formats':
				$formats = $db->get_col("SELECT distinct(pagename) FROM {$db->t_pages} WHERE lower(substring(pagename, 1, 7)) = 'format:'");
				return $this->a2wlul($formats, '', create_function('$a', 'global $rewrite; return "<a href=\"" . $rewrite->get_link(array("page"=>$a, "action"=>"edit")) . "\" onclick=\"editInsert(\'\{\{{$a}\}\}\');return false;\">" . substr($a,7) . "</a>";'));
			case 'revisions':
				$epage_name = $db->escape($this->page_name);
				$revisions = $db->get_results("SELECT id, postdate FROM {$db->t_pages} WHERE pagename = '{$epage_name}' ORDER BY postdate DESC", 'assoc');
				return $this->a2wlul($revisions, '', array(&$this, 'revision_link'), 'ul', true);
			case 'variables':
				$nw = new wikiengine();
				$nw->skip_macros[] = 'special:variables';
				$nw->getpage($this->page_name, $nil);
				return $this->rollup($this->a2wlul(array_unique($nw->used_variables), '', create_function('$a', 'return "<a href=\"#\" onclick=\"editInsert(\'\{\{Set:{$a}|}}\');return false;\">{$a}</a>";')));
			}
		}
		
		if(isset($this->inserts[$ref])) {
			$pg = $this->inserts[$ref];
		}
		else {
			if($this->page_exists($ref)) {
				$pg = $this->pageinclude($ref);
			}
		}
		$this->prep_directives[] = $ref;
		if($pg == '')
			return ""; //"<div class=\"microwiki_error\">Could not include \"{$ref}\"</div>";
		else
			return $this->rollup($pg);
	}
	
	function hasflag($flag)
	{
		return in_array($flag, $this->flags);
	}
		
	function process($body, $context = 'default')
	{
		ksort($this->context[$context]->filters, SORT_NUMERIC);
		foreach($this->context[$context]->filters as $filtary) {
			list($pattern, $replacement, $rollup, $linkindex) = $filtary;
			preg_match($pattern, $body, $processmatches);
			if($rollup) {
				$replacement = '$this->rollup(' . $replacement . ')';
				$body = preg_replace($pattern, $replacement, $body);
			}
			else {
				$body = preg_replace($pattern, $replacement, $body);
			}
		}
		if((count($this->footnotes) > 0) && (!$this->hasflag['nofootnotes'])) {
			$body .= '<ol id="wikifootnotes">';
			$footindex = 0;
			foreach($this->footnotes as $footnote) {
				$footindex++;
				$body .= "<li id=\"wikifootnotes_{$footindex}\"><sup>{$footindex}</sup>{$footnote}</li>\n";
			}
			$body .= '</ol>';
		}
		$body = $this->unroll($body);
		if(!$this->hasflag('nopee')) {
			$body = $this->autop($body);
		}
		return $body;
	}
	
	function pageinclude($pagename)
	{
		$newiki = new wikiengine($this);
		$newiki->use_format = '';
		$body = $newiki->getpage($pagename, $pagerow);
		$this->flags = array_merge($newiki->flags, $this->flags);
		return $body;
	}
	
	function getrawpage($pagename, &$pagerow, $preprocess = true, $version = '')
	{
		global $db, $mwconfig, $pluginpages;
		$norm_page = $this->normalize_str($pagename);
		//$norm_page = str_replace('_', ' ', $pagename);
		$enorm_page = $db->escape($norm_page);
		if($version == '') {
			$qry = "SELECT * FROM {$db->t_pages} WHERE pagename = '{$enorm_page}' ORDER BY postdate DESC LIMIT 1";
		}
		else {
			$qry = "SELECT * FROM {$db->t_pages} WHERE pagename = '{$enorm_page}' AND id <= {$version} ORDER BY id DESC LIMIT 1";
		}
		$pagerow = $db->get_row($qry);

		if(!$pagerow) {
			if(isset($pluginpages[$norm_page])) {
				$body = $pluginpages[$norm_page]($norm_page);
			}
			else {
				$body = $this->fileinclude('wikihome.txt', $norm_page);
			}
			if($body == '') {
				return '';
			}
			$pagerow->body = $body; //$this->fileinclude('wikihome.txt', $norm_page);
			$pagerow->title = $pagename;
		}
		
		$body = $pagerow->body;
		$body = str_replace('$', '&#36;', $body);

		if($this->page_rec == '') $this->page_rec = $pagerow;
				
		//Pre-process
		if($preprocess) $body = $this->preprocess($body);

		return $body;
	}
	
	function preprocess($body, $doreplace = true)
	{
		while(preg_match('/(?<!{){{([^{}]*?)(\\|[^{}]*)?}}/s', $body)) 
			$body = preg_replace('/(?<!{){{([^{}]*?)(\\|[^{}]*)?}}/se', 
			"\$this->macro('\\1', trim('\\2'))", 
			$body);

		return $body;
	}
	
	function get_edit_format($pagename)
	{
		global $db, $mwconfig;
		if(strpos($pagename, ':') !== false) {
			list($namesp, $basename) = explode(':', $pagename);
			$format = "edit/{$namesp}";
			if($this->page_exists("Format:{$format}")) {
				return "edit/{$namesp}";
			}
			else {
				return "edit";
			}
		}
		else {
			return "edit";
		}
		
	}
	
	function getpagenatural($pagename, $pagedata)
	{
		// PARAMS: pagename, pee, noprocess, version
		$pee = true;
		$noprocess = false;
		$version = '';
		if(strpos($params, '=')) {
			parse_str($params);
		}
		else {
			$pagename = $params;
		}
		
		if($this->page_name == '') $this->page_name = $pagename;
		
		if($this->edit_mode) {
			$this->use_format = $this->get_edit_format($pagename);
			$body = $pagedata;
		}
		else {
			$body = $this->preprocess($pagedata);
		}

		$pg = ($this->hasflag('noprocess') || $this->edit_mode) ? $body : $this->process($body);
				
		return $pg;
	}
	
	function getpage($params, &$pagerow)
	{
		global $db, $rewrite, $mwconfig;
		// PARAMS: pagename, pee, noprocess, version
		$pee = true;
		$noprocess = false;
		$version = '';
		if(strpos($params, '=')) {
			parse_str($params);
		}
		else {
			$pagename = $params;
		}
				
		if($this->page_name == '') $this->page_name = $pagename;
		 
		$pagename = $this->normalize_str($pagename);
		if(strpos($pagename, ':') !== false) {
			list($this->namespace) = explode(':', $pagename);
			$specialns = array('image', 'special', 'template');
			if(!in_array(strtolower($this->namespace), $specialns)) {
				if($this->page_exists("Format:" . $db->escape($this->namespace))) 
				$this->use_format = $this->namespace;
			}
			if(strtolower($this->namespace) == 'template') {
				$this->use_format = '';
			}
		}
		else {
			$this->namespace = '';
		}

		if($this->edit_mode) {
			$this->use_format = $this->get_edit_format($pagename);
			$body = $this->getrawpage($pagename, $pagerow, false, $version);
			$body = str_replace('&#36;', '$', $body);
		}
		else {
			$body = $this->getrawpage($pagename, $pagerow, true, $version);
			if($this->page_exists("Format:" . $db->escape(dirname($pagename)))) { 
				$this->use_format = dirname($pagename);
			}
		}

		if($this->display_name == '') $this->display_name = basename($pagerow->pagename);
		if($this->display_name == '') $this->display_name = basename($pagerow->title);
		if($this->display_name == '') $this->display_name = basename($pagename);
				
		if($version != '' && !$this->edit_mode) {
			$this->insert_before .= "<div style=\"border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;\">This version of the page was saved at " . @date('Y-m-d H:i', @strtotime($pagerow->postdate)) . " by " . $this->authorname($pagerow->author) . ".<br />";
			$viewlink = $rewrite->get_link(array("page"=>$this->page_name));
			$histlink = $rewrite->get_link(array("page"=>$this->page_name, 'action'=>'history'));
			$this->insert_before .= "View the <a href=\"{$viewlink}\">current version</a>.
				View the <a href=\"{$histlink}\">page history</a>.</div>";
		}
		
		if(isset($useformat)) {
			$this->use_format = $useformat;
		}
		$pg = ($this->hasflag('noprocess') || $this->edit_mode) ? $body : $this->process($body);
		if($this->edit_mode) $pg = htmlspecialchars($pg);
		$pg = $this->insert_before . $pg . $this->insert_after;
		if($this->use_format != '') {
			$this->hasformat = true;
			$this->base_page = $this->rollup($pg);
			$templ = $this->getrawpage('Format:' . $this->use_format, $unused, true);
			$pg = $this->unroll($this->hasflag('noprocess') ? $templ : $this->process($templ));
		}
		
		return $pg;
	}
	
	function page_exists($pg)
	{
		global $db, $mwconfig, $pluginpages;
		$norm_page = $this->normalize_str($pg);
		$epage = $db->escape($norm_page);
		$res = $db->get_var("SELECT id FROM {$db->t_pages} WHERE pagename = '{$epage}' LIMIT 1");
		if($res == 0) {
			if(isset($pluginpages[$norm_page])) return true;
			$wikihome = $this->fileinclude('wikihome.txt', $norm_page); 
			if($wikihome) return true;
		}
		return ($res > 0);
	}
	
	function clear_cache($pg)
	{
		global $db, $mwconfig;
		$norm_page = $this->normalize_str($pg);
		$epage = $db->escape($norm_page);

		$tpage = dirname($norm_page);
		while($tpage != '.' && $tpage != '') {
			$etpage = $db->escape($tpage);
			$orlinksto .= " OR linksto RLIKE '{$etpage}'";
			$tpage = dirname($tpage);
			$c++;if($c>10) die();
		}
		
		$db->query("DELETE FROM {$db->t_pages} WHERE pagename LIKE 'cache:%' AND (linksto RLIKE '{$epage}' {$orlinksto});");
	}
	
	function get_cache($cachetag)
	{
		global $db, $mwconfig;
		
		if($this->cache_off == true) return '';
		
		$npage = $db->escape('cache:' . $cachetag);
		$qry = "SELECT body FROM {$db->t_pages} WHERE pagename = '{$npage}'";
		$record = unserialize($db->get_var($qry));
		if (is_string($record)) {
			$record = /*'<!--begin cached-->' .*/ $record /*. '<!--end cached-->'*/; 
		}
		return $record;
	}

	function add_cache($cachetag, $pages, $record)
	{
		global $db, $mwconfig;
	
		$npage = $db->escape('cache:' . $cachetag);
		$pagecontent = $db->escape(serialize($record));
		$linksto = $db->escape(implode(',', (array)$pages));
		
		$db->query("DELETE FROM {$db->t_pages} WHERE pagename = '{$npage}'");
		$qry = "INSERT INTO {$db->t_pages} (
				pagename, 
				body, 
				postdate, 
				linksto
				) VALUES (";
				$qry .= "'{$npage}'";
				$qry .= ", '{$pagecontent}'";
				$qry .= ", '" . date('Y-m-d H:i:s') . "'";
				$qry .= ", '{$linksto}'";
				$qry .= ");";
		$db->query($qry);
	}
	
	function format_content($pg)
	{
		$this->base_page = $this->rollup($this->insert_before . $pg . $this->insert_after);
		if($this->page_exists('Format:' . $this->use_format)) {
			$templ = $this->getrawpage('Format:' . $this->use_format, $unused);
		}
		else {
			$templ = $this->getrawpage('Format:default', $unused);
		}
		return $this->unroll($templ);
	}
	
	function gethistory($pagename)
	{
		global $db, $mwconfig, $rewrite;
		$epage = $db->escape($pagename);
		if($changes = $db->get_results("SELECT * FROM {$db->t_pages} WHERE pagename = '{$epage}' ORDER BY postdate DESC limit 30")) {
			$output = '';
			$first = true;
			foreach($changes as $change) {
				$output .= '<tr>';
				if($first) {
					$output .= "<td> </td>";
					$first = false;
				}
				else {
					$output .= '<td><input type="radio" name="difffrom" value="' . $change->id . '" /></td>';
				}
				if(++$verct == count($changes)) {
					$output .= "<td> </td>";
				}
				else {
					$output .= '<td><input type="radio" name="diffto" value="' . $change->id . '" /></td>';
				}
				$output .= '
					<td><a href="' . $rewrite->get_link(array("page"=>$change->pagename, "action"=>"view", "tag"=>$change->id)) . '">' . date('Y-m-d H:i:s', strtotime($change->postdate)) . '</a></td>
					<td>' . $this->authorname($change->author) . '</td>
					</tr>
				';
				if($change->changenote != '') {
					$output .= '<tr><td colspan="4" class="changenote">' . $change->changenote . '</td></tr>';
				}				
			}
			$output = "
				<form class=\"wikihistory\" method=\"post\" action=\"{$_SERVER['REQUEST_URI']}\">
				<table id=\"history\">
				<thead><tr><th>From</th><th>To</th><th>Revised On</th><th>Author</th></tr></thead>
				<tbody>{$output}</tbody></table>
				<p class=\"submit\"><input type=\"submit\" name=\"diff\" value=\"Show Changes\" /></p>
				</form>
			";
		}
		else {
			$output = '<p>That page name has no history.</p>';
		}

		return $output;
	}
	
	function getdiff($pagename, $oldver, $newver)
	{
		include(dirname(__FILE__) .'/diff.php');
		global $db, $rewrite;
		
		$epage = $db->escape($pagename);
		$pages = $db->get_results("SELECT * FROM {$db->t_pages} WHERE id IN ({$oldver}, {$newver}) ORDER BY postdate ASC");
		$oldpage = $pages[0];
		$newpage = $pages[1];
		$text1 = str_replace(array("\r\n", "\r"), "\n", $oldpage->body);
		$text2 = str_replace(array("\r\n", "\r"), "\n", $newpage->body);
		$lines1 = split("\n", $text1);
		$lines2 = split("\n", $text2);
		$diff = &new Diff($lines1, $lines2);
		$formatter = &new TableDiffFormatter();
		$output = "<table class=\"wikidiff\"><thead><tr><th>";
		$output .= $this->link($rewrite->get_link(array('page'=>$pagename, 'action'=>'view', 'tag'=>$oldver)), "{$pagename} rev {$oldver}");
		$output .= "</th><th>"; 
		$output .= $this->link($rewrite->get_link(array('page'=>$pagename, 'action'=>'view', 'tag'=>$newver)), "{$pagename} rev {$newver}");
		$output .= "</th></tr></thead><tbody>"; 
		$output .= $formatter->format($diff) . "</tbody></table>";

		return $output;
	}
	
	function get_rss_page_history($page)
	{
		include(dirname(__FILE__) .'/diff.php');

		global $mwconfig, $rewrite, $db, $session;

		$epage = $db->escape($page);
		$pages = $db->get_results("SELECT * FROM {$db->t_pages} WHERE pagename = '{$epage}' ORDER BY postdate DESC limit 10");
		
		$body = '<'.'?xml version="1.0" encoding="UTF-8"?'.'><'.'?xml-stylesheet type="text/css" href="' . $rewrite->get_link(array('page'=>'Style:RSS')) . '"?'.'><!-- generator="microwiki" -'.'-><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" >';
		$body .= " <channel><title>History of {$mwconfig->wikiname}</title>
			<link>{$mwconfig->baselocation}</link>
			<description>{$t}</description>
			<copyright>Copyright ".date("Y")."</copyright>
			<pubDate>".date('D, d M Y H:i:s +0000')."</pubDate>
			<generator>microwiki</generator>
		";
	
		$oldver = '';
		$stack = '';
	
		$loginreq = -1;
		foreach($pages as $wikipage) {
			$item = '';
			$newver = $wikipage->body;
			if(stripos($newver, '{{loginonly}}') !== false) {
				if($loginreq == -1) $loginreq = 1;
				else $loginreq = 0;
				if(!$session->is_auth()) continue;
			}
			if($oldver != '') {
				$item .= "
				<item>
					<title>{$wikipage->pagename} on " . date('D, d M Y H:i:s', strtotime($wikipage->postdate)) . " </title>";
		
		  	if($usedate) {
		  		$opturl = $rewrite->get_link(array('tag'=>$wikipage->id, 'action'=>'view', 'page'=>$wikipage->pagename));
		  	}
		  	else {
		  		$opturl = $rewrite->get_link(array('page'=>$wikipage->pagename));
		  	}
		
				$item .= "
				<link>{$opturl}</link>
		
				<pubDate>".date('D, d M Y H:i:s +0000', strtotime($wikipage->postdate))."</pubDate>
		
				<category>General</category>
				<guid isPermaLink=\"false\">".md5($wikipage->title.$wikipage->id).$wikipage->title.$wikipage->id."</guid>
				<!--author id=\"{$wikipage->author}\">" . $this->authorname($wikipage->author) . "</author-->
				<description>
				Changes by ". $this->authorname($wikipage->author) .":\n";
				if($wikipage->changenote != '') {
					$item .= "NOTE:\"{$wikipage->changenote}\"\n";
				}
				if($wikipage->minoredit) {
					$item .= "[Minor Change]\n";
				}
	
				$text1 = str_replace(array("\r\n", "\r"), "\n", $oldver);
				$text2 = str_replace(array("\r\n", "\r"), "\n", $newver);
				$lines1 = split("\n", $text1);
				$lines2 = split("\n", $text2);
				$diff = &new Diff($lines2, $lines1);
				$formatter = &new TextDiffFormatter();
				$item .= $formatter->format($diff);
			
				$item .= "</description></item>";
			}
			$oldver = $newver;
			$stack .= "\n" . $item;
		}
		$body .= $stack;
		$body .= "</channel></rss>";
		$body = $this->unroll($body);
		if(($loginreq == 1) && !$session->is_auth()) $body = preg_replace('/<item>.*?<\/item>/ims', '', $body);
		return $body;
	}

	function get_rss_history()
	{	
		global $mwconfig, $rewrite, $db, $session;

		include(dirname(__FILE__) .'/diff.php');

		if(!$session->is_auth()) {
			$andwhere .= " AND (body NOT LIKE '%{{loginonly}}%')";
		}
		$andwhere .= " AND pagename NOT LIKE 'cache:%'";
		$pages = $db->get_results("SELECT * FROM {$db->t_pages} WHERE 1=1 {$andwhere} ORDER BY postdate DESC limit 10");
		
		$body = '<'.'?xml version="1.0" encoding="UTF-8"?'.'><'.'?xml-stylesheet type="text/css" href="' . $rewrite->get_link(array('page'=>'Style:RSS')) . '"?'.'><!-- generator="microwiki" -'.'-><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" >';
		$body .= " <channel><title>{$mwconfig->wikiname} Page History</title>
			<link>{$mwconfig->baselocation}</link>
			<description>{$mwconfig->wikiname} Page History</description>
			<copyright>Copyright ".date("Y")."</copyright>
			<pubDate>".date('D, d M Y H:i:s +0000')."</pubDate>
			<generator>microwiki</generator>
		";
	
		foreach($pages as $wikipage) {
			$epage = $db->escape($wikipage->pagename);	
			if($prev = $db->get_row("SELECT * FROM {$db->t_pages} WHERE pagename = '{$epage}' AND postdate < '{$wikipage->postdate}' LIMIT 1;")) {
				$text2 = str_replace(array("\r\n", "\r"), "\n", $prev->body);
				$text1 = str_replace(array("\r\n", "\r"), "\n", $wikipage->body);
				$lines1 = split("\n", $text1);
				$lines2 = split("\n", $text2);
				$diff = &new Diff($lines2, $lines1);
				$formatter = &new TextDiffFormatter();
				$bd = $formatter->format($diff);
				$chupdate = 'Changes';
			}
			else {
				$bd = htmlspecialchars($wikipage->body);
				$chupdate = 'New page';
			}

			$body .= "
		<item>
			<title>{$wikipage->pagename} on " . date('D, d M Y H:i:s', strtotime($wikipage->postdate)) . "</title>";
	
  		$opturl = $rewrite->get_link(array('page'=>$wikipage->pagename));
			$body .= "
			<link>{$opturl}</link>
	
			<pubDate>".date('D, d M Y H:i:s +0000', strtotime($wikipage->postdate))."</pubDate>
	
			<category>General</category>
			<guid isPermaLink=\"false\">".md5($wikipage->title.$wikipage->id).$wikipage->title.$wikipage->id."</guid>
			<!--author id=\"{$wikipage->author}\">" . $this->authorname($wikipage->author) . "</author-->
			<description>{$chupdate} by ". $this->authorname($wikipage->author) .":\n";
	
			if($wikipage->changenote != '')
			{
				$body .= "NOTE:\"{$wikipage->changenote}\"\n";
			}
			if($wikipage->minoredit)
			{
				$body .= "[Minor Change]\n";
			}

			$body .= $bd;		
	
			$body .= "</description>";
			$body .= "<content:encoded><![CDATA[" . str_replace("\n", "<br />\n", $bd) . "]]></content:encoded>";
			$body .= "</item>";
		}
		$body .= "</channel></rss>";
		$body = $this->unroll($body);
		return $body;
	}


	function rmkdir($dirName, $rights=0777){
		$dirName = preg_replace('/(\/){2,}|\\\+/','/', $dirName);
		$dirs = explode('/', $dirName);
		$dir = '';
		foreach ($dirs as $part) {
			$dir .= $part . '/';
			$mdir = rtrim($dir, '/');
			if($mdir == '') continue;
			if (!is_dir($mdir) && !file_exists($mdir) ) {
				mkdir($mdir, $rights);
			}
			if(!is_dir($mdir)) return false;
		}
		return true;
	}

	function thumbnailout($image, $mwidth, $mheight)
	{
		global $mwconfig;
		if(file_exists($mwconfig->imagedir . "/thumbnails/{$mwidth}x{$mheight}/{$image}")) {
			readfile($mwconfig->imagedir . "/thumbnails/{$mwidth}x{$mheight}/{$image}");
		}
		else {
			$src = ImageCreateFromJPEG($mwconfig->imagedir . '/' . $image);
			
			$org_h = imagesy($src);
			$org_w = imagesx($src);
			if (($org_w / $org_h) < ($mwidth / $mheight)) {
				$height = $mheight;
				$width  = floor ($height * $org_w / $org_h);
			} 
			else {
				$width = $mwidth;
				$height = floor ($width * $org_h / $org_w);
			}
			$img = imagecreatetruecolor ($width, $height);
			ImageCopyResampled($img, $src, 0, 0, 0, 0, $width, $height, $org_w, $org_h );
				
			$cachefile = $mwconfig->imagedir . "/thumbnails/{$mwidth}x{$mheight}/{$image}";
			if($this->rmkdir(dirname($cachefile))) {
				@ImageJPEG($img, $cachefile, 80);
			}
			else {
				die("couldn't make " . dirname($cachefile));
			}
				
			ImageJPEG($img, '', 80);
		}
	}
	
	function imageout($image, $imgattr)
	{
		global $mwconfig;
		$mod_time = filemtime($mwconfig->imagedir . '/' . $image);
		if($_SERVER['HTTP_IF_MODIFIED_SINCE']) {
			$req_time = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
		}
		else {
			$req_time = time();
		}
		header("Last-Modified: " . gmdate("D, d M Y H:i:s",$mod_time) . " GMT");
		if( $mod_time == $req_time ) {
			if ( preg_match('/cgi/', php_sapi_name()) ) {
			    header('Status: 304 Not Modified');
			    echo "\r\n\r\n";
			    exit;
			} 
			else {
			    if ( version_compare(phpversion(), '4.3.0', '>=') ) {
			        header('Not Modified', TRUE, 304);
			    } 
					else {
			        header('HTTP/1.x 304 Not Modified');
			    }
				exit;
			}
			//header("Cache-Control: max-age=86400, must-revalidate");
		}
		else {
			$pi = pathinfo($image);
			switch(strtolower($pi['extension']))
			{
			case 'jpg': header('Content-Type: image/jpg'); break;
			case 'gif': header('Content-Type: image/gif'); break;
			case 'png': header('Content-Type: image/png'); break;
			}
	
			if($imgattr == '') {
				readfile($mwconfig->imagedir . '/' . $image);
			}
			else {
				if(preg_match('/([0-9]+)x([0-9]+)/i', $imgattr, $matches)) {
					$mwidth = intval($matches[1]);
					$mheight = intval($matches[2]);
					$this->thumbnailout($image, $mwidth, $mheight);
				}
				elseif (strtolower($imgattr) == 'thumb') {
					$this->thumbnailout($image, 60, 60);
				}
				else {
					die($imageattr);
				}
			}
		}
	}
	
	function normalize_str($str)
	{
		return str_replace('_', ' ', preg_replace('/[^-a-z0-9.\s:!\/]+/i', '.', $str));
	}
	
	function renderpage($page, $tag)
	{
		global $rewrite, $session;
		$body = $this->getpage("pagename={$page}&version={$tag}", $pagerow);
		if($this->hasflag('loginonly')) {
			if($session->auth_form('custom_auth_form')) {
				return $body;
			}
			else {
				header("location: ". $rewrite->get_link(array('page'=>$mwconfig->mw_rootpage)));
				return '';
			}
		}
		else if($pagerow->body == '')
		{
			header("location: ". $rewrite->get_link(array('page'=>$page, 'action'=>'edit')));
			//die($rewrite->get_link(array('page'=>$page, 'action'=>'edit')));
			exit;
		}	
		return $body;
	}
}

$hosts = array();
if(file_exists('wikipreload.php')) include('wikipreload.php');
$mwconfig = new microwikiconfig(__FILE__, $hosts);     
if($mwconfig->regusersonly == 'WordPress') {              
  include $mwconfig->wordpress_dir . '/wp-config.php';  
}
$db = new microwikidb($mwconfig);
$tableexists = ($db->table_exists($mwconfig->db_tableprefix . 'users')) && ($db->dberror == '');
$session = new microwikisession('microwiki' . md5($mwconfig->wikiname));
$page = str_replace('!', ':', $page);
if($mwconfig->_isdomain)
  $rewrite = new microwikirewrite('http://' . $mwconfig->_domain, 'https://' . $mwconfig->_domain);
else
  $rewrite = new microwikirewrite($mwconfig->baselocation, $mwconfig->baselocation_ssl);

$wiki = new wikiengine();
$extensions = array();
$actions = array();
$accumulator = array();
$ajaxhandlers = array();
$pluginpages = array();
foreach($wiki->load_plugins() as $plugin) {
	if(file_exists($plugin)) include_once($plugin);
}
foreach(get_declared_classes() as $class) {
	if(strtolower(get_parent_class($class)) == 'wikiplugin') {
		new $class();
	}
}
$wiki->plugins_loaded();
$wiki->edited = $edited;

extract((array)$rewrite->compact($mwconfig->linkstruct=='Friendly'));

function custom_auth_form()
{
	global $wiki, $mwconfig;
	$wiki->display_name = 'Login';
	echo $wiki->getpage("pagename={$mwconfig->loginpage}&useformat=default", $pagerow);
}

function save_page($page, $data)
{
  global $mwconfig, $db, $wiki, $session, $events;
  // pagecontent, minoredit, changenote, secure
	$nw = new wikiengine();
	$nw->getpagenatural($page, $data['pagecontent']);
	$linksto = $db->escape(implode(',', $nw->linksto));
	$minoredit = isset($data['minoredit'])? 1 : 0;
	$pagecontent = $db->escape($data['pagecontent']);
	$changenote = $db->escape($data['changenote']);
	$secure = isset($data['secure'])?'1':'0';
	$npage = $db->escape($nw->normalize_str($page));
	$qry = "INSERT INTO {$db->t_pages} (
		pagename, 
		body, 
		author, 
		postdate, 
		changenote, 
		minoredit, 
		linksto,
		secure
		) VALUES (";
		$qry .= "'{$npage}'";
		$qry .= ", '{$pagecontent}'";
		$qry .= ", {$session->user_id}";
		$qry .= ", '" . date('Y-m-d H:i:s') . "'";
		$qry .= ", '{$changenote}'";
		$qry .= ", {$minoredit}";
		$qry .= ", '{$linksto}'";
		$qry .= ", {$secure}";
		$qry .= ");";
	$db->query($qry);
	
	if($db->dberror) {
		$db->get_error(true);
	}

	$wiki->clear_cache($page);
	
	$qry = "SELECT postdate FROM {$db->t_pages} WHERE pagename = '{$npage}' AND minoredit = 0 ORDER BY postdate DESC LIMIT {$mwconfig->keeplast},1";
	if($postdate = $db->get_var($qry)) {
		$qry = "DELETE FROM {$db->t_pages} WHERE pagename = '{$npage}' AND postdate < '{$postdate}';";
		$db->query($qry);
	}
	if(isset($events['post_save'])) {
		foreach($events['post_save'] as $event) {
			call_user_func($event, $page, $data);
		}
	}
}

if(!$tableexists && ($action != 'install')) {
	if($action == 'view' || $action == '') {
		if($page == '') $page = 'MicroWiki:Welcome to MicroWiki';
		$body = $wiki->fileinclude('wikihome.txt', $wiki->normalize_str($page));
		if($body == '') $action = 'install';
		else {
			$action = 'view';
		}
	}
	else $action = 'install';
}

if($tableexists && $mwconfig->regusersonly == 'internal') {
	if(stripos($page, 'style:') === false) 
		if($db->get_var("SELECT count(*) FROM {$db->t_users}") == 0)
			$action = 'newuser';
}

if($page == '') $page = $mwconfig->mw_rootpage;

/***** THE BIG SWITCH *****/
switch(strtolower($action))
{
case 'config':
case 'install':
	if(($mwconfig->lockconfig == 'yes') && ($_POST['unlock'] != substr(md5($mwconfig->db_password),0,8))) {
		die('<p>Config is locked</p>
			<form method="post"><input type="text" name="unlock" /><input type="submit" name="submit" value="Unlock"/></form>
		');
	}
	if(!$tableexists || $session->auth_form('custom_auth_form')) {
		ob_start();
		echo "<h2>Wiki Configuration</h2>\n";
		if($mwconfig->write_post()) {
			if($mwconfig->regusersonly == 'WordPress') include $mwconfig->wordpress_dir . '/wp-config.php';
			$db = new microwikidb($mwconfig);
			if($action == 'install') {
				echo "<h3>Database Upgrades</h3>\n";
				$upgrades = $db->upgrade();
				//echo "<p>Try viewing the <a href=\"{$wiki->baselocation}\">home page</a>.</p>";
				echo "<hr>\n";
			}
		}
		else if(isset($_POST['config'])) {
			echo '<p style="font-weight:bold;font-size:1.2em;border:1px solid red;padding:5px;width:100%;text-align:center;">MicroWiki failed to save the config file to disk.
			<br />Please read on...</p>
			<p>You must do one of the following:</p>
			<ul>
			<li>Allow write access to a file named "' . basename(__FILE__, '.php') . '.cfg.php" in the same directory as 
			the MicroWiki file.</li>
			<li>Save the configuration data in this text area using that name:
			<textarea style="width:100%;height:100px;">' . $mwconfig->_thisfile .'</textarea></li>
			</ul>
			';
		}
		echo '<p>Software is installed at:<br/>' . dirname(__FILE__) . '</p>';
		$mwconfig->editform(true);
		$pg = ob_get_clean();
		$wiki->use_format = 'install';
		$wiki->page_name = 'Install/Config/Upgrade';
		$wiki->display_name = 'Install/Config/Upgrade';
		$body = $wiki->format_content($pg);
	}
	break;
case 'backup':
	if($session->auth_form('custom_auth_form')) {
		$dt = date('Y-m-d');
		$backupfile = dirname(__FILE__).'/backup-'.$dt.'.txt';
		if($fp = fopen($backupfile, 'w+')) {
			$db->query("CREATE TEMPORARY TABLE px SELECT p1.pagename, max(p1.postdate) as pd FROM {$db->t_pages} as p1 group by p1.pagename");
			$pages = $db->get_results("SELECT {$db->t_pages}.* FROM px INNER JOIN {$db->t_pages} ON px.pagename = {$db->t_pages}.pagename AND px.pd = {$db->t_pages}.postdate;");
			foreach($pages as $page) {
				echo "<div>Backing up: {$page->pagename}</div>";
				fwrite($fp, "##{$page->pagename}##\n");
				fwrite($fp, "{$page->body}\n");
			}
			fclose($fp);
			echo "<div>Backup complete!</div>";
			exit;
		}
		else {
			echo "<div>Could not create backup file \"{$backupfile}\".</div>";
		}
	}
	break;
case 'upgrade':
	if($session->auth_form('custom_auth_form')) {
		if(isset($_POST['doupgrades'])) {
			$upgrades = $db->upgrade(true);
			if(count($upgrades)==0) $upgrades[] = 'No updates required.';
			$wiki->inserts['upgrades'] = $wiki->a2wlul($upgrades, '', 'ucwords');
		}
		//$wiki->page_name = 'Database Upgrades';
		$wiki->display_name = 'Database Upgrades';
		$body = $wiki->getpage("pagename=Template:default/upgrade&useformat=default", $pagerow);
	}
	break;
case 'edit':
	if($session->auth_form('custom_auth_form')) {
		if (get_magic_quotes_gpc()) {
			$_POST = array_map('stripslashes', $_POST);
		}
		if(isset($_POST['save'])) {
			//if($db->get_var("SELECT count(id) as ttl FROM {$db->t_pages} WHERE pagename = '{$page}';") > 0)
			save_page($page, $_POST);
			if($db->dberror) {
				$db->get_error(true);
			}
			else {
				header('location: ' . $rewrite->get_link(array('page'=>$page,'edited'=>'true')));
			}
			die();
			//$body = $wiki->getpage("pagename={$page}&version={$tag}", $pagerow);
		}
		else if(isset($_POST['preview'])) {
			$wiki->edit_mode = true;
			$wiki->preview_mode = true;
			$body = $wiki->getpage("pagename={$page}&version={$tag}", $pagerow);
		}
		else {
			$wiki->edit_mode = true;
			$body = $wiki->getpage("pagename={$page}&version={$tag}", $pagerow);
		}
	}
	break;
case 'image':
	$wiki->imageout($image, $imgattr);
	break;
case 'media':
	switch($imgaction) {
	case 'edit':
		if($session->auth_form('custom_auth_form')) {
			if (get_magic_quotes_gpc()) {
				$_POST = wlToolkit::stripslashes($_POST);
			}
			if(isset($_POST['save'])) {
				$nw = new wikiengine();
				$nw->getpagenatural($page, $_POST['pagecontent']);
				$norm_media = $nw->normalize_str($media);
				$linksto = $db->escape(implode(',', $nw->linksto));
				$minoredit = isset($_POST['minoredit'])? 1 : 0;
				$pagecontent = $db->escape($_POST['pagecontent']);
				$changenote = $db->escape($_POST['changenote']);
				$secure = isset($_POST['secure'])?'1':'0';
				$qry = "INSERT INTO {$db->t_pages} (
					pagename, 
					body, 
					author, 
					postdate, 
					changenote, 
					minoredit, 
					linksto,
					secure
					) VALUES (";
					$qry .= "'Media:{$norm_media}'";
					$qry .= ", '{$pagecontent}'";
					$qry .= ", {$session->user_id}";
					$qry .= ", '" . date('Y-m-d H:i:s') . "'";
					$qry .= ", '{$changenote}'";
					$qry .= ", {$minoredit}";
					$qry .= ", '{$linksto}'";
					$qry .= ", {$secure}";
					$qry .= ");";
				$db->query($qry);
				$wiki->clear_cache($page);
				header('location: ' . $rewrite->get_link(array('page'=>"Media" . SPECIAL_SEPARATOR . "{$media}")));
				exit;
			}
			else {
				$wiki->media = $media;
				$wiki->edit_mode = true;
				$body = $wiki->getpage("pagename=Media:{$media}", $pagerow);
			}
			break;
		}
	default:
		$wiki->media = $media;
		$wiki->use_format = 'media';
		$body = $wiki->getpage("pagename=Media:{$media}", $pagerow);
		break;
	}
	break;
case 'upload':
	if($session->is_auth()) {
		$pi = pathinfo($_FILES['userfile']['name']);
		if(!preg_match('/^(jpg|jpeg|gif|png)$/i', $pi['extension'])) {
			echo "File is of an unaccepted type ({$pi['extension']}).";
		}
		else {
			if(isset($_REQUEST['gallery']) && ($_REQUEST['gallery'] != '')) {
				if(!is_dir($mwconfig->imagedir . '/' . $_REQUEST['gallery'])) {
					$this->rmkdir($mwconfig->imagedir . '/' . $_REQUEST['gallery']);
				}
				$uploadFile = $mwconfig->imagedir . '/' . $_REQUEST['gallery'] . '/' . $_FILES['userfile']['name'];
				$gal = $_REQUEST['gallery'] . '/' . $_FILES['userfile']['name'];
			}
			else {
				$uploadFile = $mwconfig->imagedir . '/' . $_FILES['userfile']['name'];
				$gal = $_FILES['userfile']['name'];
			}
			$params = implode('|', $_REQUEST['params']);
			if($params != '') $params = '|' . $params;
			if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadFile)) {
				echo '<script type="text/javascript"><!--
				myValue = \'{{Image:' . $gal . $params . '}}\';
				pardoc = window.parent.document;
				myField = pardoc.getElementById(\'pagecontent\');
				if (document.selection) {
					myField.focus();
					sel = document.selection.createRange();
					sel.text = myValue;
					myField.focus();
				}
				else if (myField.selectionStart || myField.selectionStart == \'0\') {
					var startPos = myField.selectionStart;
					var endPos = myField.selectionEnd;
					myField.value = myField.value.substring(0, startPos)
					              + myValue 
			                      + myField.value.substring(endPos, myField.value.length);
					myField.focus();
					myField.selectionStart = startPos + myValue.length;
					myField.selectionEnd = startPos + myValue.length;
				} else {
					myField.value += myValue;
					myField.focus();
				}
				
				location.href = "' . $rewrite->get_link(array('page'=>$page)) . '";
				//--></script>';
				//header("location: ". $rewrite->get_link(array('page'=>$page)));
				//die($rewrite->get_link(array('page'=>$page)));
			}
			else {
				echo "Upload Error.";
			}
		}	
	}
	exit;
case 'password':
	switch($mwconfig->regusersonly) {
	case 'WordPress':
		header('location:' . get_settings('siteurl') . '/wp-admin/profile.php');
		die();
	case 'internal':
		if($session->auth_form('custom_auth_form')) {
			$pg = "<form method=\"post\"><table><tr><th>Username:</th><td>{$session->username}</td></tr>";
			$pg .= "<tr><th>Password:</th><td><input type=\"password\" name=\"pass1\" value=\"\" /></td></tr>";
			$pg .= "<tr><th>Confirm Password:</th><td><input type=\"password\" name=\"pass2\" value=\"\" /></td></tr>";
			$pg .= "<tr><td colspan=\"2\" style=\"text-alignment:right;\"><input type=\"submit\" name=\"submit\" value=\"Change Password\" /></td></tr>";
			$pg .= "</table></form>";
			if(isset($_POST['pass1'])) {
				if($_POST['pass1'] != $_POST['pass2']) {
					$wiki->insert_before = '<div style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">The two password fields must have the same value to update your password.  Please try again.</div>';
				}
				elseif($_POST['pass1'] == '') {
					$wiki->insert_before = '<div style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">The password must be set to a value.  Please try again.</div>';
				}
				else {
					switch(SEC_FUNC) {
						case 'sha1': $tpass = sha1($_POST['pass1']); break;
						case '2*md5': $tpass = md5(md5($_POST['pass1'])); break;
					}
					$db->query("UPDATE {$db->t_users} SET password='{$tpass}' WHERE username='{$session->username}';");
					$wiki->insert_before = '<div style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">Your password has been updated.  You may need to log in again with the new password to continue.</div>';
				}
			}
			$body = $wiki->format_content($pg);
		}
		break;
	case 'none':
		$body = $wiki->format_content('<p>This wiki does not have logins.  You can\'t change your password when you don\'t have a login.</p>');  
	}
	break;
case 'newuser':
	switch($mwconfig->regusersonly) {
	case 'internal':
		if($db->get_var("SELECT count(*) FROM {$db->t_users}") == 0 || $mwconfig->regcreateuser == 'no' || $session->auth_form('custom_auth_form')) {
			$pg = "<form method=\"post\" id=\"wikinewuser\"><table><tr><th>Username:</th><td><input type=\"text\" name=\"user\" value=\"{$session->username}\" /></td></tr>";
			$pg .= "<tr><th>Password:</th><td><input type=\"password\" name=\"pass1\" value=\"\" /></td></tr>";
			$pg .= "<tr><th>Confirm Password:</th><td><input type=\"password\" name=\"pass2\" value=\"\" /></td></tr>";
			$pg .= "<tr><td colspan=\"2\" style=\"text-alignment:right;\" class=\"actions\"><input type=\"submit\" name=\"submit\" value=\"Create Account\" /></td></tr>";
			$pg .= "</table></form>";
			if(isset($_POST['pass1'])) {
				if($_POST['pass1'] != $_POST['pass2']) {
					$wiki->insert_before = '<div style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">The two password fields must have the same value to update your password.  Please try again.</div>';
				}
				elseif($_POST['pass1'] == '') {
					$wiki->insert_before = '<div style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">The password must be set to a value.  Please try again.</div>';
				}
				elseif($db->get_var("SELECT count(*) FROM {$db->t_users} WHERE username='" . $db->escape($_POST['user']) . "';")) {
					$wiki->insert_before = '<div style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">That username already exists.  Please try again.</div>';
				}
				else {
					switch(SEC_FUNC) {
						case 'sha1': $tpass = sha1($_POST['pass1']); break;
						case '2*md5': $tpass = md5(md5($_POST['pass1'])); break;
					}
					$db->query("INSERT INTO {$db->t_users} (username, password) values('" . $db->escape($_POST['user']) . "', '{$tpass}');");
					$wiki->insert_before = '<div style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">' . "The new account, \"{$_POST['user']}\", has been created.</div>";
				}
			}
		}
		else {
			$pg = "<p>Creating new users via this page can only be done by logged-in users.</p>"; 
		}
		break;
	case 'WordPress':
		header('location: ' . get_settings('siteurl') . '/wp-register.php');
		die();
	case 'none':
		$pg = "<p>This wiki does not use logins.  You cannot create a new login.</p>";
		break; 
	}
	$body = $wiki->format_content($pg);
	break;
case 'logout':
	$session->end_session();
	$wiki->insert_before = '<p style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">You are now logged out.</p>';
	$body = $wiki->renderpage($page, $tag);
	break;
case 'rebuild':
	if($session->auth_form('custom_auth_form')) {
		$nw = new wikiengine();
		$nw->getpage($page, $pagerow);
		$linksto = implode(',', $nw->linksto);
		$minoredit = 0;
		$epage = $db->escape($page);
		$qry = "SELECT ID FROM {$db->t_pages} WHERE pagename = '{$epage}' ORDER BY postdate DESC limit 1";
		$rid = $db->get_var($qry);
		$qry = "UPDATE {$db->t_pages} SET
			linksto = '{$linksto}'
			WHERE id = '{$rid}';";
		$db->query($qry);
		$db->get_error();
	}
	$body = "Rebuilt '{$page}'.";
	$body .= '<script type="text/javascript">window.parent.loadnext();</script>';
	break;
case 'rebuildall':
	$body = '
	<html><head><title>Rebuild All</title>
	<script type="text/javascript"><!--//
	var pageindex = 0;
	function loadnext()
	{
		var pagenames = [';
	
	$pages = $db->get_col("SELECT DISTINCT pagename FROM {$db->t_pages}");
	foreach($pages as $pg) {
		if(strtolower(substr($pg, 0, 6)) == 'media' . SPECIAL_SEPARATOR)
			$pg = substr($pg, 6);
		$body .= "'{$pg}',";
	}
	
	$body .= '];
		pageindex++;
		document.getElementById("pctdone").style.width = 200 * pageindex / pagenames.length;
		if(pageindex < pagenames.length)
		{
			rebuild = "' . match_scheme($mwconfig->baselocation) . '/" + pagenames[pageindex] + "/rebuild";
			document.getElementById("reloader").src = rebuild;
		}
	}
	//--></script>
	</head><body>
	<h1>Rebuilding Entire Dataset</h1>
	<p>Please wait...</p>
	<div style="width:200px;height:10px;background-color:red;margin-bottom:30px;"><div id="pctdone" style="width:0px;height:10px;background-color:green;"></div></div>
	<iframe id="reloader" style="border:0px;" src="about:blank" ></iframe>
	<script type="text/javascript">loadnext()</script>
	</body></html>
	';
	break;
case 'badlinks':
	$pages = array();
	$linksto = $db->get_col("SELECT linksto FROM {$db->t_pages} where linksto <> ''");
	foreach($linksto as $pagelinks) {
		$plary = explode(',', $pagelinks);
		foreach($plary as $pagelink) {
			$pagelink = strtolower($pagelink);
			if(substr($pagelink, 0, 6) == 'media' . SPECIAL_SEPARATOR) continue; //$pagelink = substr($pagelink, 6);
			$pages[] = $wiki->normalize_str($pagelink);
		}
	}
	$pages = array_unique($pages);
	$existing = $db->get_col("SELECT DISTINCT pagename FROM {$db->t_pages};");
	$existing = array_map(create_function('$a', 'return strtolower($a);'), $existing);
	$pages = array_diff($pages, $existing);
	$pg = '';
	foreach($pages as $nolink) {
		$pg .= '<li>' . $wiki->link($nolink) . "</li>\n";
	}
	$pg = "<ul>\n{$pg}</ul>\n";
	
	$wiki->display_name = 'Bad Links';
	$body = $wiki->format_content($pg);
	break;
case 'new':
	$pages = array();
	$newpages = $db->get_col("SELECT distinct(pagename) FROM {$db->t_pages} WHERE pagename NOT LIKE 'cache:%' ORDER BY postdate DESC limit 10");
	foreach($newpages as $newpage) {
		$pg .= '<li>' . $wiki->link($newpage) . "</li>\n";
	}
	$pg = "<ul>\n{$pg}</ul>\n";
	
	$wiki->display_name = 'Recent Pages';
	$body = $wiki->format_content($pg);
	break;
case 'all':
	$pages = array();
	$newpages = $db->get_col("SELECT distinct(pagename) FROM {$db->t_pages} WHERE pagename NOT LIKE 'cache:%' AND pagename NOT LIKE 'Deleted:%' ORDER BY pagename");
	foreach($newpages as $newpage) {
		$pg .= '<li>' . $wiki->link($newpage) . "</li>\n";
	}
	$pg = "<ul>\n{$pg}</ul>\n";
	
	$wiki->display_name = 'All Pages';
	$body = $wiki->format_content($pg);
	break;
case 'orphans':
	$pages = array();
	$linksto = $db->get_col("SELECT linksto FROM {$db->t_pages} where linksto <> ''");
	foreach($linksto as $pagelinks) {
		$plary = explode(',', $pagelinks);
		foreach($plary as $pagelink) {
			$pagelink = strtolower($pagelink);
			if(substr($pagelink, 0, 6) == 'media' . SPECIAL_SEPARATOR) continue; //$pagelink = substr($pagelink, 6);
			$pages[] = $wiki->normalize_str($pagelink);
		}
	}
	$pages = array_unique($pages);
	$existing = $db->get_col("SELECT DISTINCT pagename FROM {$db->t_pages};");
	$existing = array_map(create_function('$a', 'return strtolower($a);'), $existing);
	$pages = array_diff($existing, $pages);
	$pg = '';
	foreach($pages as $nolink) {
		$pg .= '<li>' . $wiki->link($nolink) . "</li>\n";
	}
	$pg = "<ul>\n{$pg}</ul>\n";
	
	$wiki->display_name = 'Orphaned Pages';
	$body = $wiki->format_content($pg);
	break;
case 'history':
	if(isset($_POST['diff'])) {
		$wiki->use_format = 'diff';
		$body = $wiki->format_content($wiki->gethistory($page) . $wiki->getdiff($page, $_POST['difffrom'], $_POST['diffto']));
	}
	else {
		$wiki->use_format = 'history';
		$body = $wiki->format_content($wiki->gethistory($page));
	}
	break;
case 'delete':
	if($session->auth_form('custom_auth_form')) {
		if(isset($_POST['delete'])) {
			if($_POST['delete'] == 'Yes') {
				$epage = $db->escape($page);
				$db->query("UPDATE {$db->t_pages} SET pagename = 'Deleted:{$epage}' WHERE pagename = '{$epage}';");
				$wiki->clear_cache($page);
			}
			header("location: ". $rewrite->get_link(array('page'=>$page)));
			die($rewrite->get_link(array('page'=>$page)));
		}
		else {
			$wiki->insert_before = '<form method="post" style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">Are you sure you want to delete this page?<br/><input type="submit" name="delete" value="Yes"/><input type="submit" name="delete" value="No"/></form>';
			$body = $wiki->renderpage($page, $tag);
			$wiki->content_type = '';
		}
	}
	break;
case 'move':
	if($session->auth_form('custom_auth_form')) {
		if(isset($_POST['move'])) {
			if(($_POST['move'] == 'Move') && ($_POST['newpagename'] != '')) {
				$newpagename = $_POST['newpagename'];
				$enewpagename = $db->escape($newpagename);
				$epage = $db->escape($page);
				if($db->get_var("SELECT count(id) FROM {$db->t_pages} WHERE pagename = '{$enewpagename}';")>0) {
					$wiki->insert_before = '<form method="post" style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;"><strong>That page name already exists!</strong></br>Where would you like to move this page?<br/><input type="text" name="newpagename" /><input type="submit" name="move" value="Move"/><input type="submit" name="move" value="Cancel"/></form>';
					$body = $wiki->renderpage($page, $tag);
				}
				else {
					$db->query("UPDATE {$db->t_pages} SET pagename = '{$enewpagename}' WHERE pagename = '{$epage}';");
					$wiki->clear_cache($page);
				}
			}
			header("location: ". $rewrite->get_link(array('page'=>$page)));
			die($rewrite->get_link(array('page'=>$page)));
		}
		else {
			$wiki->insert_before = '<form method="post" style="border:1px dotted red;background-color:white;color:red;padding:5px;margin:5px;">Where would you like to move this page?<br/><input type="text" name="newpagename" /><input type="submit" name="move" value="Move"/><input type="submit" name="move" value="Cancel"/></form>';
			$body = $wiki->renderpage($page, $tag);
			$wiki->content_type = '';
		}
	}
	break;
case 'recentrss':
	$body = $wiki->get_rss_history();
	$wiki->content_type = 'text/xml';
	break;
case 'rss':
	$epage = $db->escape($page);
	$newpages = $db->get_results("SELECT * FROM {$db->t_pages} WHERE pagename = '{$epage}' ORDER BY postdate DESC limit 10");
	$body = $wiki->get_rss_page_history($page);
	$wiki->content_type = 'text/xml';
	break;
case 'ajax':
	if (get_magic_quotes_gpc()) {
		$_POST = wlToolkit::stripslashes($_POST);
	}
	$handler = $_POST['handler'];
	if(isset($ajaxhandlers[$handler])) {
		call_user_func($ajaxhandlers[$handler]);
	}
	else {
		echo "No handler for {$handler}";
	}
	die();
	break; 
case 'view':
default:
	if(isset($actions[$action])) {
		$body = call_user_func($actions[$action]);
	}
	else {
		$body = $wiki->renderpage($page, $tag);
	}
	break;
}

if($edited && !$wiki->hasformat) {
	$nw = new wikiengine();
	$nw->page_name = $page;
	$prebar = $nw->renderpage('special:prebar', false);
	$wiki->content_type = $nw->content_type;
	$body = $prebar . $body;
}

//Remove unknown unrolls from output:
$body = preg_replace('/\x02B[0-9A-F]{32}\x02E/i', '<span class="wikimacrocontent">Macro Content</span>', $body);
if(preg_match('/{{{location:(.*?)}}}/e', $body, $match)) {
	header('location:' . $match[1]);
	die();
}

/***** FINAL OUTPUT *****/
if($wiki->content_type != '') {
	header('Content-Type: ' . $wiki->content_type);
}
else {
	$body .= '<!-- ' .  (microtime(true) - $wikistarttime) . ' seconds -->';
}
header("HTTP/1.1 200 OK");
header("Status: 200 OK");
echo trim($body);
